#python #beautifulsoup
#python #beautifulsoup
Вопрос:
Я разбираю большой html
документ. Я использовал groups
для «группировки» текста и разделения с помощью nn
. Весь текст находится в <font> </font>
тегах документа.
Каждая группа имеет 5 полей, Serial#.........,Cust#...........,Customer Name...,BILL TO NO NAME.,DATE......
Мне нужно использовать Cust#...........
из каждой «группы» и сравнить ее с любой другой группой в списке, чтобы найти дубликат Cust#...........
.
Если найден дубликат, то мне нужно добавить BILL TO NO NAME.
в каждую группу дубликат Cust#...........
Пример html:
Serial#......... 12345678974566321nCust#........... 123456nCustomer Name... Humpfrey BearnBILL TO NO NAME. Bill To: 001166 - Some CompanynDATE...... 01/01/00nn'Serial#......... sgfdsfd546545645nCust#........... 123456nCustomer Name... Humpfrey BearnBILL TO NO NAME. Bill To: 0165487 - Some Other CompanynDATE...... 01/01/00nn'Serial#......... Jgfdhdgfhgfdh4545nCust#........... 88483nCustomer Name... John SmithnBILL TO NO NAME. Bill To: 0146897 - Some CompanynDATE...... 01/01/00nn'Serial#......... JF2SJads5dsafdsafnCust#........... 015648nCustomer Name... Eric CantonanBILL TO NO NAME. Bill To: 8888154 - Man UtdnDATE...... 01/01/00nn'Serial#......... JdsfrfdsgHG091797nCust#........... 015648nCustomer Name... Eric CantonanBILL TO NO NAME. Bill To: 9876524 - Big Big CompanynDATE...... 01/01/00nn'
Вывод, который мне нужен, это: Serial#......... 12345678974566321nCust#........... 123456nCustomer Name... Humpfrey BearnBILL TO NO NAME. Bill To: 001166 - Some Company Bill To: 0165487 - Some Other CompanynDATE...... 01/01/00nn',Serial#......... JF2SJads5dsafdsafnCust#........... 015648nCustomer Name... Eric CantonanBILL TO NO NAME. Bill To: 8888154 - Man Utd Bill To: 9876524 - Big Big CompanynDATE...... 01/01/00nn'
В моем выводе были опущены дубликаты, основанные на Cust # ……xxxxx, но я просто пытаюсь немного яснее показать ожидаемый результат. Я могу отсортировать дубликаты позже.
Сокращенная версия того, что у меня есть на данный момент, остальное несущественно.
from bs4 import BeautifulSoup
import re
import urllib
import os
with open(r'.html', 'r') as f:
html_string = f.read()
soup = BeautifulSoup(html_string, 'html.parser')
groups = soup.font.text.replace('Serial#', 'xxxSerial#').split('xxx')
Комментарии:
1. Можете ли вы немного подробнее объяснить, какова связь с вашим примером ввода и желаемым результатом?
BILL TO NO NAME
Тег присутствует в каждой записи в вашем примере ввода. Указанный вами желаемый результат, по-видимому, является просто единственным экземпляром двух дублированных записей, но, похоже, никаких дополнительныхBILL TO NO NAME
тегов добавлено не было, и вы также ничего не сказали об исключении не дубликатов в вашем результате. Было бы полезно некоторое дополнительное разъяснение.2. Во входных данных также нет HTML, который я вижу — он выглядит как обычный текст. Я имею в виду, обычный текст является частью допустимого HTML, но я не уверен, зачем вам нужно использовать BeautifulSoup здесь, кажется, что любой метод обработки строк был бы приемлем. Это верно?
3. У меня есть некоторый код, который позже опустит дубликаты, не нужно беспокоиться об этом. Правильно, мне не нужен красивый суп, я просто начал с этого и продолжал.. Открыт для любых идей
4. Хорошо, спасибо. В чем я все еще не уверен, так это в следующем: вы написали «Если найден дубликат, мне нужно добавить СЧЕТ БЕЗ ИМЕНИ». Но каждая запись в вашем примере ввода уже содержит «СЧЕТ БЕЗ ИМЕНИ». И ваш вывод не отображается в каких-либо дополнительных тегах «СЧЕТ БЕЗ ИМЕНИ». Итак, если исключение дубликатов не является целью, и в тексте уже есть «СЧЕТ БЕЗ НАЗВАНИЯ», что вы пытаетесь сделать — просто определить, какие записи имеют повторяющиеся
Cust#
значения?
Ответ №1:
Это не совсем похоже на ожидаемый результат в вашем вопросе, но это может подвести вас достаточно близко:
bills = """[your html above]"""
groups = bills.replace('Serial#','xxxSerial#').split('xxx')
cust_nums = []
ng= []
for group in groups[1:]:
items = group.split('n')
cn = items[1].split('. ')[1]
bill = items[3].split('. ')[1]
if cn not in cust_nums:
cust_nums.append(items[1].split('. ')[1])
else:
items[3] =' ' bill
ng.append(items[:-2])
ng
Вывод:
[['Serial#......... sgfdsfd546545645',
'Cust#........... 123456',
'Customer Name... Humpfrey Bear',
'BILL TO NO NAME. Bill To: 0165487 - Some Other Company Bill To: 0165487 - Some Other Company',
'DATE...... 01/01/00'],
['Serial#......... JdsfrfdsgHG091797',
'Cust#........... 015648',
'Customer Name... Eric Cantona',
'BILL TO NO NAME. Bill To: 9876524 - Big Big Company Bill To: 9876524 - Big Big Company',
'DATE...... 01/01/00']]
Ответ №2:
Если ваша цель — идентифицировать повторяющиеся Cust#
значения, вот один из подходов:
import re
sep = "Serial#"
def get_cust_number(entry):
""" Isolate the customer ID number. """
pattern = re.compile("Cust#[^0-9] (d )")
return pattern.findall(entry)[0]
# return a list of dicts, each element has full entry and customer id
parsed = [{"full_entry": sep x, "cust_id": get_cust_number(x)}
for x in data.split(sep) if x]
# example parsed element
{'full_entry': "Serial#......... 12345678974566321nCust#........... 123456nCustomer Name... Humpfrey BearnBILL TO NO NAME. Bill To: 001166 - Some CompanynDATE...... 01/01/00nn'",
'cust_id': '123456'}
Теперь используйте a set
для поиска дубликатов Cust#
и сохранения дублирующихся записей в dupes
:
seen = set()
dupes = list()
# iterate over each entry, store :cust_id: values in :seen: set.
# if :cust_id: is already in :seen:, it is a dupe. store it in :dupes:.
for entry in parsed:
if entry['cust_id'] in seen:
dupes.append(entry['full_entry'])
else:
seen.add(entry['cust_id'])
dupes
["Serial#......... sgfdsfd546545645nCust#........... 123456nCustomer Name... Humpfrey BearnBILL TO NO NAME. Bill To: 0165487 - Some Other CompanynDATE...... 01/01/00nn'",
"Serial#......... JdsfrfdsgHG091797nCust#........... 015648nCustomer Name... Eric CantonanBILL TO NO NAME. Bill To: 9876524 - Big Big CompanynDATE...... 01/01/00nn'"]
Я не понимаю, почему в вашем выводе есть вторая запись «Humpfrey Bear», но первая запись «Eric Cantona». Этот ответ генерирует список только повторяющихся выходных данных (что означает, что первой записи там нет).