Как искать элементы из списка в строку и извлекать ключевые слова рядом с соответствием - PullRequest
2 голосов
/ 06 мая 2019

Я работаю над проектом, для которого мне нужно извлечь номера счетов из тела письма.Номера счетов могут быть где угодно в теле письма, которое я пытаюсь найти, используя код Python.Проблема в том, что отправители электронной почты не использовали стандартные ключевые слова, они использовали различные слова, чтобы упомянуть номера счетов, например.Номер счета, номер счета, номер счета, номер счета.inv-no и т. д.

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

После прочтения сотен электронных писем я могу определить большинство общих слов, которые используются перед номерами счетов, и создал их список (около 15 ключевых слов).Но я не могу найти этот список ключевых слов в строке, чтобы получить ключевые слова рядом с ними, чтобы идентифицировать номер счета-фактуры, также номер счета-фактуры может быть как числовым, так и буквенно-цифровым, что увеличило сложность.

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

inv_list = ['invoice number','inv no','invoice#','invoice','invoices','inv number','invoice-number','inv-number','inv#','invoice no.'] # list of keywords used before invoice number

example_string = 'Hi Team, Could you please confirm the status of payment 
for invoice# 12345678 and AP-8765432?
Also, please confirm the status of existing invoice no. 7652908.
Thanks'

# Basic code to test if any word from inv_list exists in example_string

for item in inv_list:
    if item in example_string:
        print(item)

# gives the output like 

invoice#
invoice no.

Затем, после поиска в течение нескольких часов, я нашел эту функцию как получить список со словами, которыерядом с конкретным словом в строке в python , но я не могу использовать это для списка слов.Я попытался:

def get_next_words(mailbody, invoice_text_list, sep=' '):
    mail_body_words = mailbody.split(sep)
    for word in invoice_text_list:
        if word in mail_body_words:
            yield next(mail_body_words)

words = get_next_words(example_string,inv_list)

for w in words:
    print(w)

и получил

TypeError: объект 'list' не является итератором

Ожидаемый результат - возвращать ключевые слова из 'example_string ', за которым следует любое ключевое слово, совпадающее с' inv_list '(я предполагаю, что могу определить номер счета-фактуры по возвращенному совпадению)

Для данного примера выходные данные должны быть:

Match1: 'invoice#'             
Expected Output: '12345678'

Match2: 'invoice no.'          
Expected Output:  '7652908'

Пожалуйста, дайте мне знать, если требуется дополнительная информация, любая помощь приветствуется !!

Ответы [ 3 ]

1 голос
/ 06 мая 2019

возможно, не самый эффективный код, но работает ... Необходимы два случая, чтобы отличить fe inv no 06363636 и inv 06363636 из-за пробела между inv и no ...

arr = example_string.split(' ')
for ix in range(len(arr)):
    try: 
        if arr[ix]+" "+arr[ix+1] in inv_list:
            print(arr[ix+2].strip('.'))
        elif arr[ix] in inv_list:
            print(arr[ix+1].strip('.'))
    except IndexError:
        pass
1 голос
/ 06 мая 2019

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

inv_list = {'invoice number','inv no','invoice#','invoice','invoices','inv number','invoice-number','inv-number','inv#','invoice no.'}

def get_next_words(mailbody, invoice_text_list, sep=' '):
    mail_body_words = mailbody.split(sep)
    for i in range(len(mail_body_words)):
        if mail_body_words[i] in invoice_text_list:
            yield mail_body_words[i+1]
        elif f'{mail_body_words[i]} {mail_body_words[i+1]}' in invoice_text_list:
            yield mail_body_words[i+1]
words = get_next_words(example_string, inv_list)

for w in words:
    print(w)
0 голосов
/ 07 мая 2019

Я внес некоторые правки в ответ, данный atsteich, чтобы сделать его более полезным в моем сценарии, в основном я хочу записать только числовые значения в качестве номера счета-фактуры и удалить некоторые дополнительные знаки препинания, которые могут идти вместе с номером счета-фактуры.

Ниже приведен код:

arr = example_string.split(' ')
remove_symbols = str.maketrans("","",".,-")

for ix in range(len(arr)):
    try: 
        if arr[ix]+" "+arr[ix+1] in inv_list and arr[ix+2].translate(remove_symbols).isdigit():
            print('Invoice number found:'+arr[ix+2].translate(remove_symbols))
        elif arr[ix] in inv_list and arr[ix+1].translate(remove_symbols).isdigit():
            print('Invoice number found:'+arr[ix+1].translate(remove_symbols))
     except IndexError:
        pass

Спасибо всем за поддержку!

...