将BeautifulSoup分割为两个Soup树
有很多方法可以把BeautifulSoup的解析树拆分成元素列表或者获取标签的字符串。但是,似乎没有办法在拆分的同时保持树的完整性。
我想在这个代码片段(soup)中按<br />
进行拆分。用字符串拆分很简单,但我想保持结构,想要得到一系列的解析树。
s="""<p>
foo<br />
<a href="http://...html" target="_blank">foo</a> | bar<br />
<a href="http://...html" target="_blank">foo</a> | bar<br />
<a href="http://...html" target="_blank">foo</a> | bar<br />
<a href="http://...html" target="_blank">foo</a> | bar
</p>"""
soup=BeautifulSoup(s)
当然,我可以用[BeautifulSoup(i) for i in str(soup).split('<br />')]
来实现,但这样看起来很丑,而且我有太多链接了,不想这么做。
用soup.next和soup.previousSibling()在soup.findAll('br')上进行迭代是可以的,但这样得到的不是解析树,而只是包含的所有元素。
有没有办法从一个BeautifulSoup标签中提取出完整的子树,同时保持所有的父子关系和兄弟关系呢?
为了更清楚:
结果应该是一个包含BeautifulSoup对象的列表,我可以通过output[0].a、output[1].text等方式进一步遍历拆分后的soup。按<br />
拆分的结果会返回一个包含所有链接的列表,方便我进一步处理,这正是我需要的。上面代码片段中的所有链接,包括文本、属性和后面的“bar”,都是每个链接的描述。
1 个回答
0
如果你不介意原来的树结构被改变,我会用 .extract()
方法来处理 <br />
标签,这样就可以简单地把它们从树中移除:
>>> for br in soup.find_all('br'): br.extract()
...
<br/>
<br/>
<br/>
<br/>
>>> soup
<html><body><p>
foo
<a href="http://...html" target="_blank">foo</a> | bar
<a href="http://...html" target="_blank">foo</a> | bar
<a href="http://...html" target="_blank">foo</a> | bar
<a href="http://...html" target="_blank">foo</a> | bar
</p></body></html>
这仍然是一个完整的工作树:
>>> soup.p
<p>
foo
<a href="http://...html" target="_blank">foo</a> | bar
<a href="http://...html" target="_blank">foo</a> | bar
<a href="http://...html" target="_blank">foo</a> | bar
<a href="http://...html" target="_blank">foo</a> | bar
</p>
>>> soup.p.a
<a href="http://...html" target="_blank">foo</a>
不过,你其实根本不需要移除这些标签,就能达到你想要的效果:
for link in soup.find_all('a'):
print link['href'], ''.join(link.stripped_strings), link.next_sibling
结果是:
>>> for link in soup.find_all('a'):
... print link['href'], ''.join(link.stripped_strings), link.next_sibling
...
http://...html foo | bar
http://...html foo | bar
http://...html foo | bar
http://...html foo | bar
无论我们是否先把 <br/>
标签从树中移除,结果都是一样的。