如果我有这样的事情:
<p>blah</p>
<p foo:bar="something">blah</p>
<p foo:xxx="something">blah</p>
我如何让 beautifulsoup 选择具有 foo 命名空间属性的元素?
例如,我希望返回第二个和第三个 p 元素。
如果我有这样的事情:
<p>blah</p>
<p foo:bar="something">blah</p>
<p foo:xxx="something">blah</p>
我如何让 beautifulsoup 选择具有 foo 命名空间属性的元素?
例如,我希望返回第二个和第三个 p 元素。
从文档中:
Beautiful Soup 提供了一个名为 attrs 的特殊参数,您可以在这些情况下使用它。attrs 是一个类似于关键字参数的字典:
soup.findAll(id=re.compile("para$"))
# [<p id="firstpara" align="center">This is paragraph <b>one</b>.</p>,
# <p id="secondpara" align="blah">This is paragraph <b>two</b>.</p>]
soup.findAll(attrs={'id' : re.compile("para$")})
# [<p id="firstpara" align="center">This is paragraph <b>one</b>.</p>,
# <p id="secondpara" align="blah">This is paragraph <b>two</b>.</p>]
如果需要对名称为 Python 保留字的属性(如 class、for 或 import)进行限制,可以使用 attrs;或名称是 Beautiful Soup 搜索方法的非关键字参数的属性:名称、递归、限制、文本或 attrs 本身。
from BeautifulSoup import BeautifulStoneSoup
xml = '<person name="Bob"><parent rel="mother" name="Alice">'
xmlSoup = BeautifulStoneSoup(xml)
xmlSoup.findAll(name="Alice")
# []
xmlSoup.findAll(attrs={"name" : "Alice"})
# [parent rel="mother" name="Alice"></parent>]
因此,对于您给定的示例:
soup.findAll(attrs={ "foo" : re.compile(".*") })
# or
soup.findAll(attrs={ re.compile("foo:.*") : re.compile(".*") })
BeautifulSoup(版本 3 和 4)似乎没有将命名空间前缀视为任何特殊内容。它只是将命名空间前缀和命名空间属性视为名称中恰好有冒号的属性。
因此,要<p>
在命名空间中查找具有属性的元素foo
,您只需遍历所有属性键并检查是否attr.startswith('foo')
:
import BeautifulSoup as bs
content = '''\
<p>blah</p>
<p foo:bar="something">blah</p>
<p foo:xxx="something">blah</p>'''
soup = bs.BeautifulSoup(content)
for p in soup.find_all('p'):
for attr in p.attrs.keys():
if attr.startswith('foo'):
print(p)
break
产量
<p foo:bar="something">blah</p>
<p foo:xxx="something">blah</p>
使用lxml,您可以通过 XPath 进行搜索,它确实支持按命名空间搜索属性的语法:
import lxml.etree as ET
content = '''\
<root xmlns:foo="bar">
<p>blah</p>
<p foo:bar="something">blah</p>
<p foo:xxx="something">blah</p></root>'''
root = ET.XML(content)
for p in root.xpath('p[@foo:*]', namespaces={'foo':'bar'}):
print(ET.tostring(p))
产量
<p xmlns:foo="bar" foo:bar="something">blah</p>
<p xmlns:foo="bar" foo:xxx="something">blah</p>