Используя BeautifulSoup для разбора строк, разделенных <br>тегами? - PullRequest
9 голосов
/ 21 февраля 2010

У меня есть страница, которая выглядит так:

Company A<br />
123 Main St.<br />
Suite 101<br />
Someplace, NY 1234<br />
<br />
<br />
<br />
Company B<br />
456 Main St.<br />
Someplace, NY 1234<br />
<br />
<br />
<br />

Иногда есть два, а не три тега "br", разделяющих записи. Как бы я использовал BeautifulSoup для анализа этого документа и извлечения полей? Я в замешательстве, потому что нужные мне фрагменты текста не содержатся в абзацах (или аналогичных) тегах, которые я могу просто перебрать.

Ответы [ 5 ]

6 голосов
/ 10 сентября 2014

Вы должны посмотреть на атрибут .strings, найденный в тегах, а затем использовать "\ n" .join () для этого.

2 голосов
/ 21 февраля 2010

Получив этот HTML-фрагмент, просто используйте регулярное выражение для замены <br />, за которым следует необязательный символ новой строки на одну новую строку, а затем разделите ее на несколько новых строк. Это должно привести к нескольким отдельным абзацам, которые вы можете обработать вручную.

0 голосов
/ 26 мая 2017

У меня более тонкая проблема. Это, как я решил

html=html.replace('<br>','<br />')
0 голосов
/ 21 февраля 2010

Возможно, вы могли бы использовать эту функцию:

def partition_by(pred, iterable):
    current = None
    current_flag = None
    chunk = []
    for item in iterable:
        if current is None:
            current = item
            current_flag = pred(current)
            chunk = [current]
        elif pred(item) == current_flag:
            chunk.append(item)
        else:
            yield chunk
            current = item
            current_flag = not current_flag
            chunk = [current]
    if len(chunk) > 0:
        yield chunk

Добавьте что-нибудь, чтобы проверить, является ли тег <br /> или символом новой строки:

def is_br(bs):
    try:
        return bs.name == u'br'
    except AttributeError:
        return False

def is_br_or_nl(bs):
    return is_br(bs) or u'\n' == bs

(или что-то еще более подходящее ... Я не очень хорош с BeautifulSoup.)

Затем используйте partition_by(is_br_or_nl, cs), чтобы получить (для cs установлено BeautifulSoup.BeautifulSoup(your_example_html).childGenerator())

[[u'Company A'],
 [<br />],
 [u'\n123 Main St.'],
 [<br />],
 [u'\nSuite 101'],
 [<br />],
 [u'\nSomeplace, NY 1234'],
 [<br />, u'\n', <br />, u'\n', <br />, u'\n', <br />],
 [u'\nCompany B'],
 [<br />],
 [u'\n456 Main St.'],
 [<br />],
 [u'\nSomeplace, NY 1234'],
 [<br />, u'\n', <br />, u'\n', <br />, u'\n', <br />]]

Это должно быть достаточно просто для обработки.

Чтобы обобщить это, вам, вероятно, придется написать предикат, чтобы проверить, является ли его аргумент тем, о чем вы заботитесь ... Тогда вы можете использовать его с partition_by, чтобы все остальное смешалось. Обратите внимание, что вещи, которые вас интересуют, также объединены - вам нужно обрабатывать каждый элемент каждого второго списка, созданного результирующим генератором, начиная с первого, который включает в себя вещи, которые вас волнуют.

0 голосов
/ 21 февраля 2010

Вы можете сначала немного поработать, прежде чем что-либо. например, измените все новые строки на пробелы, затем замените 2 вхождения и больше <br /> на какой-либо другой разделитель, такой как |. после этого вы можете получить свои поля.

html="""
Company A<br />
123 Main St.<br />
Suite 101<br />
Someplace, NY 1234<br />
<br />
<br />
<br />
Company B<br />
456 Main St.<br />
Someplace, NY 1234<br />
<br />
<br />
<br />
"""
import re
newhtml=html.replace("\n","")
pat=re.compile("(<br \/>){2,}",re.DOTALL|re.M)
print pat.sub("|",newhtml)

выход

$ ./python.py
Company A<br />123 Main St.<br />Suite 101<br />Someplace, NY 1234|Company B<br />456 Main St.<br />Someplace, NY 1234|

Теперь информация о вашей компании разделена трубами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...