Извлечение содержимого тега на основе значения содержимого с помощью BeautifulSoup - PullRequest
3 голосов
/ 18 января 2012

У меня есть HTML-документ следующего формата.

<p>&nbsp;&nbsp;&nbsp;1. Content of the paragraph <i> in italic </i> but not <b> strong </b> <a href="url">ignore</a>.</p>

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

Ожидаемый результат: Содержание абзаца курсивом, но не сильно.

Как лучше всего это сделать?

Кроме того, следующий фрагмент кода возвращает TypeError: аргумент типа 'NoneType' не повторяется

soup = BSoup(page)
for p in soup.findAll('p'):
    if '&nbsp;&nbsp;&nbsp;' in p.string:
        print p

Спасибо за предложения.

Ответы [ 4 ]

5 голосов
/ 18 января 2012

Ваш код не выполняется, потому что tag.string установлен, если у тега есть только один дочерний элемент, а у этого дочернего элемента NavigableString

Вы можете добиться того, чего хотите, извлекая тег a:

from BeautifulSoup import BeautifulSoup

s = """<p>&nbsp;&nbsp;&nbsp;1. Content of the paragraph <i> in italic </i> but not <b> strong </b> <a href="url">ignore</a>.</p>"""
soup = BeautifulSoup(s, convertEntities=BeautifulSoup.HTML_ENTITIES)

for p in soup.findAll('p'):
    for a in p.findAll('a'):
        a.extract()
    print ''.join(p.findAll(text=True))
1 голос
/ 18 января 2012

Проблема, связанная с string, заключается в том, что string, как описано в документации , доступно только:

если тег имеет только один дочерний узел, и этот дочерний узел является строкой

Следовательно, в вашем случае p.string - это None, и вы не можете перебрать его. Чтобы получить доступ к содержимому тега, вы должны использовать p.contents (это список, содержащий теги) или p.text (это строка со всеми удаленными тегами).

В вашем случае вы, вероятно, ищете что-то вроде этого:

>>> ''.join([str(e) for e in soup.p.contents
                    if not isinstance(e, BeautifulSoup.Tag)
                       or e.name != 'a'])
>>> '&nbsp;&nbsp;&nbsp;1. Content of the paragraph <i> in italic </i> but not <b> strong </b> .'

Если вам нужно также удалить префикс `'', я бы использовал регулярное выражение для удаления этой части из конечной строки.

1 голос
/ 18 января 2012

Я думаю, вам просто нужно пройтись по тегам внутри p и собрать нужные строки.

Используя lxml , вы можете использовать XPath:

import lxml.html as LH
import re

content = '''\
<p>&nbsp;&nbsp;&nbsp;1. Content of the paragraph <i> in italic </i> but not <b> strong </b> <a href="url">ignore</a>.</p>'''

doc = LH.fromstring(content)
ptext = ''.join(doc.xpath('//p/descendant-or-self::*[not(self::a)]/text()'))
pat = r'^.*\d+.\s*'
print(re.sub(pat,'',ptext))

выход:

Content of the paragraph  in italic  but not  strong  .
0 голосов
/ 22 апреля 2013

http://www.crummy.com/software/BeautifulSoup/bs4/doc/#get-text

Если вам нужна только текстовая часть документа или тега, вы можете использовать метод get_text (). Он возвращает весь текст в документе или под тегом в виде одной строки Unicode. (приведено в документации по ссылке выше)

...