4
votes

Extraire les noms d'une chaîne avec python Regex

J'ai essayé d'extraire des noms d'une chaîne, mais je ne semble pas près du succès.

Voici le code:

string = "555-1239Moe Szyslak(636) 555-0113Burns, C. Montgomery555 -6542Rev. Timothy Lovejoy555 8904Ned Flanders636-555-3226Simpson, Homer5553642Dr. Julius Hibbert"
regex = re.compile(r'([A-Z][a-z]+(?: [A-Z][a-z]\.)? [A-Z][a-z]+)')
print(regex.findall(string))

Voici le résultat que j'obtiens. ['Moe Szyslak', 'Timothy Lovejoy', 'Ned Flanders ',' Julius Hibbert ']


0 commentaires

4 Réponses :


3
votes

Extraire des noms humains même en anglais est notoirement difficile. L'expression régulière suivante résout votre problème particulier mais peut échouer sur d'autres entrées (par exemple, elle ne capture pas les noms avec des tirets):

TITLE = r"(?:[A-Z][a-z]*\.\s*)?"
NAME1 = r"[A-Z][a-z]+,?\s+"
MIDDLE_I = r"(?:[A-Z][a-z]*\.?\s*)?"
NAME2 = r"[A-Z][a-z]+"

re.findall(TITLE + NAME1 + MIDDLE_I + NAME2, string)
#['Moe Szyslak', 'Burns, C. Montgomery', 'Rev. Timothy Lovejoy', 
# 'Ned Flanders', 'Simpson, Homer', 'Dr. Julius Hibbert']

Et avec les titres:

re.findall(r"[A-Z][a-z]+,?\s+(?:[A-Z][a-z]*\.?\s*)?[A-Z][a-z]+", string)
#['Moe Szyslak', 'Burns, C. Montgomery', 'Timothy Lovejoy', 
# 'Ned Flanders', 'Simpson, Homer', 'Julius Hibbert']


2 commentaires

Merci beaucoup monsieur. Mais comment obtenir les titres? Dr. et Rev. etc.


Vous n'avez jamais mentionné les titres dans votre question. Voir la réponse mise à jour.



1
votes

Voici une approche utilisant des comparaisons de largeur nulle pour isoler chaque nom:

(?:(?<=^)|(?<=[^A-Za-z.,]))
Lookbehind and assert either the start of the string, or a non matching character
(?:(?=[^A-Za-z.,])|(?=$))
Lookahead and asser either the end of the string or a non matching character

Le modèle réel correspondant est le suivant:

[A-Za-z.,]+(?: [A-Za-z.,]+)*

Ceci dit pour correspondre à une lettre, un point ou un point majuscule ou minuscule, suivi d'un espace et d'un ou plusieurs caractères identiques, zéro fois ou plus.

De plus, nous utilisons les contours suivants sur la gauche et à droite de ce modèle:

string = "555-1239Moe Szyslak(636) 555-0113Burns, C. Montgomery555 -6542Rev. Timothy Lovejoy555 8904Ned Flanders636-555-3226Simpson, Homer5553642Dr. Julius Hibbert"
result = re.findall(r'(?:(?<=^)|(?<=[^A-Za-z.,]))[A-Za-z.,]+(?: [A-Za-z.,]+)*(?:(?=[^A-Za-z.,])|(?=$))', string)

print(result)

['Moe Szyslak', 'Burns, C. Montgomery', 'Rev. Timothy Lovejoy', 'Ned Flanders',
 'Simpson, Homer', 'Dr. Julius Hibbert']


0 commentaires

-1
votes

J'extraction des entités pour les noms d'instance avec spacy en un rien de temps. Avec spacy, vous pouvez compter sur des modèles de langage pré-entraînés, qui ont une connaissance approfondie des noms et des titres courants.

  1. Étape: configurez Spacy et téléchargez le modèle de langue anglaise pré-entraîné import spacy
    import en_core_web_sm nlp = en_core_web_sm.load ()

  2. Étape: créer un document spacy doc = nlp ('555-1239Moe Szyslak (636) 555-0113Burns, C. Montgomery555-6542Rev. Timothy Lovejoy555 8904Ned Flanders636-555-3226Simpson, Homer5553642Dr. Julius Hibbert')

  3. Étape: récupérez les balises pour tous les jetons du document qui sont étiquetés comme personne print ([(X.text, X.label_) for X in doc.ents if X.label_ == PERSON])


1 commentaires

(555, 555, C. Montgomery555, Timothy Lovejoy555, Flanders636, 555, Julius Hibbert) - n'a pas l'air correct.



3
votes

Les expressions rationnelles sophistiquées prennent du temps à composer et sont difficiles à maintenir. Dans ce cas, j'aurais tendance à rester simple:

re.findall (r "[^ () 0-9 -] +", chaîne)

sortie:

['Moe Szyslak', '', 'Burns, C. Montgomery', '', 'Rév. Timothy Lovejoy ',' ',' Ned Flanders ',' Simpson, Homer ',' Dr. Julius Hibbert ']

Si les blancs sont un problème, je filtrerais la list(filter(str.strip,list))


1 commentaires

Mais certains noms ont des tirets, conservez-les.