在学到BeautifulSoup库的兄弟节点有了疑惑,希望见到这篇文章的各位大神们能帮我解决这个疑惑。
以下是出现问题的代码,没有报错,只是实现与我期望的不同。
from bs4 import BeautifulSoup
sibling_html = """
<html>
<body>
<p><p id="p1">biubiubiu</p><p id="p2">piupiupiu</p>
<p>哔哩哔哩</p>
<a class="brother" href="www.baidu.com" id="link1">Lazer</a>
<a id="link2"><b>text1</b><c>text2</c></a>
<a id="link3" href="wwww.163.com">163</a>
</body>
</html>
"""
sibling_soup = BeautifulSoup(sibling_html, 'lxml')
br = sibling_soup.p
while br.next_sibling != None:
print br
br = br.next_sibling
根据百度,兄弟节点是同级的节点,我理解在代码中<p><p id="p1">biubiubiu</p><p id="p2">piupiupiu</p>、<p>哔哩哔哩</p>、<a class="brother" href="www.baidu.com" id="link1">Lazer</a>都是同级的节点,所以
print br #打印出第一个p标签的节点,预期是打印出<p><p id='p1'>biubiubiu</p><p id='p2'>piupiupiu</p></p>
实际上打印的是:
<p></p>
理论上得到的下一个节点是
<p>哔哩哔哩</p>
实际上打印出来的下一个节点是:
<p id="p1">biubiubiu</p>
即原本是子节点的p1、p2被当成了p的兄弟节点,经过朋友的指点,用beautifulsoup对象.prettify来打印网页解析结果。
print sibling_soup.prettify
#打印出来的解析结果
#<html>\n<body>\n<p></p><p id="p1">biubiubiu</p><p id="p2">piupiupiu</p>\n
#<p>\u54d4\u54e9\u54d4\u54e9</p>\n
#<a class="brother" href="www.baidu.com" id="link1">Lazer</a>\n<a #id="link2"><b>text1</b><c>text2</c></a>\n
#<a href="wwww.163.com" id="link3">163</a>\n</body>\n</html>\n>
可以看到lxml解析器将第一个p的结束标签自动添加了上去,导致p1、p2变成和p同级的节点,在BeautifulSoup构造方法里修改解析器为python自带的解析器html.parser:
sibling_soup = BeautifulSoup(sibling_html, 'html.parser')
#打印出来的解析结果
#<html>\n<body>\n<p><p id="p1">biubiubiu</p><p id="p2">piupiupiu</p></p>\n
#<p>\u54d4\u54e9\u54d4\u54e9</p>\n<a class="brother" href="www.baidu.com" id="link1">Lazer</a>\n
#<a id="link2"><b>text1</b><c>text2</c></a>\n<a href="wwww.163.com" #id="link3">163</a>\n</body>\n</html>\n>
用了html.parser解析器后,网页解析正常,此时再print出所有兄弟字节就成功了:
#输出结果
<p><p id="p1">biubiubiu</p><p id="p2">piupiupiu</p></p>
<p>哔哩哔哩</p>
<a class="brother" href="www.baidu.com" id="link1">Lazer</a>
<a id="link2"><b>text1</b><c>text2</c></a>
<a href="wwww.163.com" id="link3">163</a>
而中间有换行,可能是因为网页解析将换行、空格等也一并解析了,当成是与p、a标签同级的子节点。
总结:当遇到输出节点与预想不一致时,print下beautifulsoup对象.prettify查看网页解析结果,确认是否是解析器导致的出入,如果是,更改解析器再查看结果。
附上从教程转来的解析器对照表:
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup,"html.parser") | 1. Python的内置标准库 2. 执行速度适 3. 中文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup,"lxml") | 1. 速度快 2. 文档容错能力强 | 需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup,["lxml-xml"]) BeautifulSoup(markup,"xml") | 1. 速度快 2. 唯一支持XML的解析器 | 需要安装C语言库 |
html5lib | BeautifulSoup(markup,"html5lib") | 1. 最好的容错性 2. 以浏览器的方式解析文档 3. 生成HTML5格式的文档 | 速度慢,不依赖外部扩展 |