私がこのようなものを持っている場合:
<p>blah</p>
<p foo:bar="something">blah</p>
<p foo:xxx="something">blah</p>
foo 名前空間の属性を持つ要素を選択するように beautifulsoup を取得するにはどうすればよいですか?
たとえば、2 番目と 3 番目の p 要素が返されるようにします。
私がこのようなものを持っている場合:
<p>blah</p>
<p foo:bar="something">blah</p>
<p foo:xxx="something">blah</p>
foo 名前空間の属性を持つ要素を選択するように beautifulsoup を取得するにはどうすればよいですか?
たとえば、2 番目と 3 番目の 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>]
class、for、importなど、名前がPythonの予約語である属性に制限を設ける必要がある場合は、attrsを使用できます。または、名前がBeautiful Soup検索メソッドのキーワード以外の引数である属性:name、recursive、limit、text、または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>