我有一个Html文档,格式如下。
<p> 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 ' ' in p.string:
print p
谢谢你的建议。
您的代码失败,因为如果标记只有一个子级并且该子级是NavigableString
,则会设置tag.string
您可以通过提取a
标签来实现您想要的:
from BeautifulSoup import BeautifulSoup
s = """<p> 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))
您在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'])
>>> ' 1. Content of the paragraph <i> in italic </i> but not <b> strong </b> .'
如果还需要删除"前缀,我会使用正则表达式从最终字符串中删除该部分。
我认为您只需要遍历p
中的标记并收集所需的字符串。
使用lxml,可以使用XPath:
import lxml.html as LH
import re
content = '''
<p> 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 .
http://www.crummy.com/software/BeautifulSoup/bs4/doc/#get-文本
如果只需要文档或标记的文本部分,可以使用get_text()方法。它以单个Unicode字符串的形式返回文档中或标记下的所有文本。(在上面链接中的文档中给出)