Beautiful Soup 4 常见问题
本章节总结了一些 Beautiful Soup 4 的常见问题,有遇到相关问题可以按照相应的措施进行处理。
代码诊断
如果想知道Beautiful Soup到底怎样处理一份文档,可以将文档传入 diagnose()
方法(Beautiful Soup 4.2.0中新增),Beautiful Soup会输出一份报告,说明不同的解析器会怎样处理这段文档,并标出当前的解析过程会使用哪种解析器:
from bs4.diagnose import diagnose
data = open("bad.html").read()
diagnose(data)
# Diagnostic running on Beautiful Soup 4.2.0
# Python version 2.7.3 (default, Aug 1 2012, 05:16:07)
# I noticed that html5lib is not installed. Installing it may help.
# Found lxml version 2.3.2.0
#
# Trying to parse your data with html.parser
# Here's what html.parser did with the document:
# ...
diagnose()
方法的输出结果可能帮助你找到问题的原因,如果不行,还可以把结果复制出来以便寻求他人的帮助
文档解析错误
文档解析错误有两种.一种是崩溃,Beautiful Soup尝试解析一段文档结果却抛除了异常,通常是 HTMLParser.HTMLParseError
.还有一种异常情况,是Beautiful Soup解析后的文档树看起来与原来的内容相差很多.
这些错误几乎都不是Beautiful Soup的原因,这不会是因为Beautiful Soup得代码写的太优秀,而是因为Beautiful Soup没有包含任何文档解析代码.异常产生自被依赖的解析器,如果解析器不能很好的解析出当前的文档,那么最好的办法是换一个解析器.更多细节查看 安装解析器 章节.
最常见的解析错误是 HTMLParser.HTMLParseError: malformed start tag
和 HTMLParser.HTMLParseError: bad end tag
.这都是由Python内置的解析器引起的,解决方法是 安装lxml或html5lib
最常见的异常现象是当前文档找不到指定的Tag,而这个Tag光是用眼睛就足够发现的了. find_all()
方法返回,而 find()
方法返回 None .这是Python内置解析器的又一个问题: 解析器会跳过那些它不知道的tag.解决方法还是 安装lxml或html5lib
版本错误
-
SyntaxError: Invalid syntax
(异常位置在代码行: ROOT_TAG_NAME = u'[document]'
),因为Python2版本的代码没有经过迁移就在Python3中窒息感 -
ImportError: No module named HTMLParser
因为在Python3中执行Python2版本的Beautiful Soup -
ImportError: No module named html.parser
因为在Python2中执行Python3版本的Beautiful Soup -
ImportError: No module named BeautifulSoup
因为在没有安装BeautifulSoup3库的Python环境下执行代码,或忘记了BeautifulSoup4的代码需要从 bs4
包中引入 -
ImportError: No module named bs4
因为当前Python环境下还没有安装BeautifulSoup4
解析成XML
默认情况下,Beautiful Soup会将当前文档作为HTML格式解析,如果要解析XML文档,要在 BeautifulSoup
构造方法中加入第二个参数 “xml”:
soup = BeautifulSoup(markup, "xml")
当然,还需要 安装lxml
解析器的错误
- 如果同样的代码在不同环境下结果不同,可能是因为两个环境下使用不同的解析器造成的.例如这个环境中安装了lxml,而另一个环境中只有html5lib, 解析器之间的区别 中说明了原因.修复方法是在
BeautifulSoup
的构造方法中中指定解析器 - 因为HTML标签是 大小写敏感 的,所以3种解析器再出来文档时都将tag和属性转换成小写.例如文档中的 <TAG></TAG> 会被转换为 <tag></tag> .如果想要保留tag的大写的话,那么应该将文档 解析成XML .
杂项错误
-
UnicodeEncodeError: 'charmap' codec can't encode character u'\xfoo' in position bar
(或其它类型的 UnicodeEncodeError
)的错误,主要是两方面的错误(都不是Beautiful Soup的原因),第一种是正在使用的终端(console)无法显示部分Unicode,参考 Python wiki ,第二种是向文件写入时,被写入文件不支持部分Unicode,这时只要用 u.encode("utf8")
方法将编码转换为UTF-8. -
KeyError: [attr]
因为调用 tag['attr']
方法而引起,因为这个tag没有定义该属性.出错最多的是 KeyError: 'href'
和 KeyError: 'class'
.如果不确定某个属性是否存在时,用 tag.get('attr')
方法去获取它,跟获取Python字典的key一样 -
AttributeError: 'ResultSet' object has no attribute 'foo'
错误通常是因为把 find_all()
的返回结果当作一个tag或文本节点使用,实际上返回结果是一个列表或 ResultSet
对象的字符串,需要对结果进行循环才能得到每个节点的 .foo
属性.或者使用 find()
方法仅获取到一个节点 -
AttributeError: 'NoneType' object has no attribute 'foo'
这个错误通常是在调用了 find()
方法后直节点取某个属性 .foo 但是 find()
方法并没有找到任何结果,所以它的返回值是 None
.需要找出为什么 find()
的返回值是 None
.
如何提高效率
Beautiful Soup对文档的解析速度不会比它所依赖的解析器更快,如果对计算时间要求很高或者计算机的时间比程序员的时间更值钱,那么就应该直接使用 lxml .
换句话说,还有提高Beautiful Soup效率的办法,使用lxml作为解析器.Beautiful Soup用lxml做解析器比用html5lib或Python内置解析器速度快很多.
安装 cchardet 后文档的解码的编码检测会速度更快
解析部分文档 不会节省多少解析时间,但是会节省很多内存,并且搜索时也会变得更快.
更多建议: