企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 常见问题 ## 代码诊断 如果想知道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没有包含任何文档解析代码.异常产生自被依赖的解析器,如果解析器不能很好的解析出当前的文档,那么最好的办法是换一个解析器.更多细节查看 [安装解析器](#id9) 章节. 最常见的解析错误是 `HTMLParser.HTMLParseError: malformed start tag` 和 `HTMLParser.HTMLParseError: bad end tag` .这都是由Python内置的解析器引起的,解决方法是 [安装lxml或html5lib](#id9) 最常见的异常现象是当前文档找不到指定的Tag,而这个Tag光是用眼睛就足够发现的了. `find_all()` 方法返回 [] ,而 `find()` 方法返回 None .这是Python内置解析器的又一个问题: 解析器会跳过那些它不知道的tag.解决方法还是 [安装lxml或html5lib](#id9) ## 版本错误 * `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](#id9) ## 解析器的错误 * 如果同样的代码在不同环境下结果不同,可能是因为两个环境下使用不同的解析器造成的.例如这个环境中安装了lxml,而另一个环境中只有html5lib, [解析器之间的区别](#id49) 中说明了原因.修复方法是在 `BeautifulSoup` 的构造方法中中指定解析器 * 因为HTML标签是 [大小写敏感](http://www.w3.org/TR/html5/syntax.html#syntax) 的,所以3种解析器再出来文档时都将tag和属性转换成小写.例如文档中的 `<TAG></TAG>` 会被转换为 `<tag></tag>` .如果想要保留tag的大写的话,那么应该将文档 [解析成XML](#xml) . ## 杂项错误 * `UnicodeEncodeError: 'charmap' codec can't encode character u'\xfoo' in position bar` (或其它类型的 `UnicodeEncodeError` )的错误,主要是两方面的错误(都不是Beautiful Soup的原因),第一种是正在使用的终端(console)无法显示部分Unicode,参考 [Python wiki](http://wiki.Python.org/moin/PrintFails) ,第二种是向文件写入时,被写入文件不支持部分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](http://lxml.de/) . 换句话说,还有提高Beautiful Soup效率的办法,使用lxml作为解析器.Beautiful Soup用lxml做解析器比用html5lib或Python内置解析器速度快很多. 安装 [cchardet](http://pypi.Python.org/pypi/cchardet/) 后文档的解码的编码检测会速度更快 [解析部分文档](#id58) 不会节省多少解析时间,但是会节省很多内存,并且搜索时也会变得更快.