Извлечение имен из строки с помощью Python Regex - PullRequest
2 голосов
/ 16 марта 2019

Я пытался извлечь имена из строки, но, похоже, не близко к успеху.

Вот код:

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))

Это вывод, который я получаю. ['Moe Szyslak', 'Timothy Lovejoy', 'Ned Flanders', 'Julius Hibbert']

Ответы [ 4 ]

2 голосов
/ 16 марта 2019

Необычные регулярные выражения требуют времени для составления и их трудно поддерживать.В этом случае я бы хотел сохранить это простым:

re.findall(r"[^()0-9-]+", string)

вывод:

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

Если пробелы являютсявопрос, я бы отфильтровал list(filter(str.strip,list))

2 голосов
/ 16 марта 2019

Извлечение человеческих имен даже на английском языке, как известно, очень сложно. Следующее регулярное выражение решает вашу конкретную проблему, но может давать сбой на других входах (например, оно не захватывает имена с тире):

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']

И с заголовками:

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']

В качестве примечания, нет необходимости составлять регулярное выражение, если вы не планируете использовать его повторно.

0 голосов
/ 16 марта 2019

Я извлекаю сущности для имен экземпляров со spacy в кратчайшие сроки. С spacy вы можете положиться на предварительно обученные языковые модели, которые обладают обширными знаниями об общих именах и названиях.

  1. Шаг: настройте spacy и загрузите предварительно подготовленную модель английского языка import spacy<br> import en_core_web_sm nlp = en_core_web_sm.load()

  2. Шаг: создать просторный документ doc = nlp('555-1239Moe Szyslak(636) 555-0113Burns, C. Montgomery555 -6542Rev. Timothy Lovejoy555 8904Ned Flanders636-555-3226Simpson, Homer5553642Dr. Julius Hibbert')

  3. Шаг: получить теги для всех токенов в документе, которые помечены как лица print([(X.text, X.label_) for X in doc.ents if X.label_ == PERSON])

0 голосов
/ 16 марта 2019

Вот один подход, использующий обходные пути нулевой ширины для выделения каждого имени:

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']

Фактический шаблон соответствует этому:

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

Это означает совпадение с любой заглавной или строчной буквой, точкой или точкой, за которым следует пробел и один или несколько одинаковых символов, ноль или более раз.

Кроме того, мы используем следующие обходные пути слева и справа от этого шаблона:

(?:(?<=^)|(?<=[^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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...