I numeri di telefono per i collegamenti in Python
-
23-08-2019 - |
Domanda
Sto lavorando un pezzo di codice per trasformare i numeri di telefono in link per cellulare -. Ho capito, ma ci si sente veramente sporca
import re
from string import digits
PHONE_RE = re.compile('([(]{0,1}[2-9]\d{2}[)]{0,1}[-_. ]{0,1}[2-9]\d{2}[-_. ]{0,1}\d{4})')
def numbers2links(s):
result = ""
last_match_index = 0
for match in PHONE_RE.finditer(s):
raw_number = match.group()
number = ''.join(d for d in raw_number if d in digits)
call = '<a href="tel:%s">%s</a>' % (number, raw_number)
result += s[last_match_index:match.start()] + call
last_match_index = match.end()
result += s[last_match_index:]
return result
>>> numbers2links("Ghost Busters at (555) 423-2368! How about this one: 555 456 7890! 555-456-7893 is where its at.")
'Ghost Busters at <a href="tel:5554232368">(555) 423-2368</a>! How about this one: <a href="tel:5554567890">555 456 7890</a>! <a href="tel:5554567893">555-456-7893</a> is where its at.'
C'è qualche cosa che potrebbe ristrutturare il regex o il metodo l'espressione regolare che sto usando per fare questo pulitore?
Aggiorna
Per chiarire, la mia domanda non è sulla correttezza del mio regex - mi rendo conto che è limitato. Invece mi chiedo se qualcuno avesse eventuali commenti per il calcolo delle substiting nei collegamenti per i numeri di telefono - c'è comunque potrei usare re.replace
o qualcosa di simile che al posto del hackery stringa che ho
Soluzione
Nizza prima ripresa :) Credo che questa versione è un po 'più leggibile (e probabilmente un po' minuscolo più veloce). La cosa fondamentale da notare qui è l'uso di re.sub . ci tiene lontano dalle brutte indici partita ...
import re
PHONE_RE = re.compile('([(]{0,1}[2-9]\d{2}[)]{0,1}[-_. ]{0,1}[2-9]\d{2}[-_. ]{0,1}\d{4})')
NON_NUMERIC = re.compile('\D')
def numbers2links(s):
def makelink(mo):
raw_number = mo.group()
number = NON_NUMERIC.sub("", raw_number)
return '<a href="tel:%s">%s</a>' % (number, raw_number)
return PHONE_RE.sub(makelink, s)
print numbers2links("Ghost Busters at (555) 423-2368! How about this one: 555 456 7890! 555-456-7893 is where its at.")
Una nota: Nella mia pratica, ho notato, non molto di un aumento di velocità pre-compilazione di semplici espressioni regolari come i due che sto utilizzando, anche se si sta utilizzando loro migliaia di volte. Il modulo re può avere una sorta di caching interna -. Non si preoccupò di leggere la fonte e verificare
Inoltre, ho sostituito il metodo di controllo di ogni personaggio per vedere se è in string.digits
con un altro re.sub()
perché penso che la mia versione è più leggibile, non perché sono certo che funziona meglio (anche se potrebbe).
Altri suggerimenti
Il tuo regexp analizza solo un formato specifico, che non è lo standard internazionale. Se ti limiti a un solo paese, si può lavorare.
In caso contrario, lo standard internazionale è ITU E.123 : "notazione per i numeri telefonici nazionali ed internazionali, indirizzi e gli indirizzi Web e-mail "
Prima di tutto, catturando in modo affidabile i numeri di telefono con una sola espressione regolare è notoriamente difficile, con una forte tendenza ad essere impossibile. Non tutti i paesi ha una definizione di un "numero di telefono", che è stretto come è negli Stati Uniti Anche negli Stati Uniti, le cose sono più complicate di quello che sembrano (dal articolo Wikipedia sul Piano di numerazione nordamericano ):
- A) Codice del paese: il prefisso opzionale ( "1" o "1" o "001")
-
((00|\+)?1)?
-
- B) Codice Piano di Numerazione Area (NPA): non può iniziare con 1, cifra 2 non può essere 9
-
[2-9][0-8][0-9]
-
- C) Codice di Borsa (NXX): non può iniziare con 1, non può finire con "11", parentesi opzionali
-
\(?[2-9](00|[2-9]{2})\)?
-
- D) Codice stazione: quattro cifre, non possono essere tutti 0 (suppongo)
-
(?!0{4})\d{4}
-
- E) un'estensione opzionale può seguire
-
([x#-]\d+)?
-
- S) parti del numero sono separati da spazi, trattini, punti (o no)
-
[. -]?
-
Quindi, l'espressione regolare di base per gli Stati Uniti potrebbe essere:
((00|\+)?1[. -]?)?\(?[2-9][0-8][0-9]\)?[. -]?[2-9](00|[2-9]{2})[. -]?(?!0{4})\d{4}([. -]?[x#-]\d+)?
| A |S | | B | S | C | S | D | S | E |
E questo è solo per il piano di numerazione relativamente banali della Stati Uniti, e anche lì certamente non è che copre tutte le sottigliezze. Se si vuole rendere affidabile è necessario sviluppare una bestia simile per tutte le lingue di input che ci si attende.
Un paio di cose che ripulire il regex esistente senza realmente cambiare la funzionalità:
Sostituire {0,1} con?, [(] Con ([)] con). È inoltre potrebbe anche solo rendere il vostro [2-9] B e A \ D pure, in modo da poter fare quei modelli essere \ d {3} e \ d {4} per l'ultima parte. Dubito che sarà davvero aumentare il tasso di falsi positivi.
Perché non riutilizzare il lavoro degli altri - per esempio, da RegExpLib.com ?
Il mio secondo suggerimento è quello di ricordare ci sono altri paesi oltre gli Stati Uniti, e non pochi di loro hanno telefoni ;-) Per favore, non dimenticarti di noi durante il vostro sviluppo del software.
Inoltre, v'è uno standard per la formattazione dei numeri di telefono; E.123 . Il mio ricordo dello standard è che ciò che descrive non corrisponde bene con l'uso popolare.
Edit: ho confuso G.123 e E.123. Ops. Puntelli Bortzmeyer