Beautiful Soup – 故障处理
错误处理
在BeautifulSoup中,有两种主要的错误需要被处理。这两种错误不是来自于你的脚本,而是来自于片段的结构,因为BeautifulSoup的API会抛出一个错误。
这两个主要错误如下 −
属性错误(AttributeError)
它是在点符号没有找到当前HTML标签的同级标签时引起的。例如,你可能遇到过这样的错误,因为缺少 “anchor标签”,cost-key会抛出一个错误,因为它遍历并需要一个anchor标签。
关键错误(KeyError)
如果缺少所需的HTML标签属性,这个错误就会发生。例如,如果我们在一个片段中没有data-pid属性,pid键将抛出key-error。
为了避免上述两个列举的错误,当解析一个结果时,该结果将被绕过,以确保一个畸形的片段不会被插入数据库中 –
except(AttributeError, KeyError) as er:
pass
diagnose()
每当我们发现在理解BeautifulSoup对我们的文档或HTML所做的任何困难时,只需将其传递给diagnose()函数。在将文档文件传递给diagnose()函数时,我们可以显示不同分析器的列表如何处理该文档。
下面是一个例子来演示诊断()函数的使用 —
from bs4.diagnose import diagnose
with open("20 Books.html",encoding="utf8") as fp:
data = fp.read()
diagnose(data)
输出
解析错误
有两种主要类型的解析错误。当你把你的文档送入BeautifulSoup时,你可能会得到一个类似HTMLParseError的异常。你也可能得到一个意外的结果,即BeautifulSoup的解析树看起来与解析文档的预期结果有很大不同。
没有一个解析错误是由BeautifulSoup引起的。这是由于我们使用的外部解析器(html5lib,lxml),因为BeautifulSoup不包含任何解析器代码。解决上述解析错误的方法之一是使用另一个解析器。
from HTMLParser import HTMLParser
try:
from HTMLParser import HTMLParseError
except ImportError, e:
# From python 3.5, HTMLParseError is removed. Since it can never be
# thrown in 3.5, we can just define our own class as a placeholder.
class HTMLParseError(Exception):
pass
Python 内置的 HTML 解析器会导致两个最常见的解析错误,HTMLParser.HTMLParserError: 畸形的开始标签和 HTMLParser.HTMLParserError: 坏的结束标签,要解决这个问题,是使用另一个解析器主要是:lxml 或 html5lib。
另一种常见的意外行为是,你无法找到一个你知道在文档中的标签。然而,当你运行 find_all() 返回 [] 或 find() 返回 None。
这可能是由于python内置的HTML解析器有时会跳过它不理解的标签。
XML解析器错误
默认情况下,BeautifulSoup包将文档解析为HTML,然而,它非常容易使用,并以一种非常优雅的方式使用beautifulsoup4来处理不符合格式的XML。
要把文档解析为XML,你需要有lxml解析器,你只需要把 “xml “作为第二个参数传给Beautifulsoup构造函数 —
soup = _BeautifulSoup(markup, "lxml-xml")
或
soup = _BeautifulSoup(markup, "xml")
一个常见的XML解析错误是–
AttributeError: 'NoneType' object has no attribute 'attrib'
这可能发生在使用find()或findall()函数时,某些元素丢失或未被定义。
其他解析错误
下面是我们将在本节中讨论的一些其他解析错误。
环境问题
除了上面提到的解析错误之外,你可能还会遇到其他的解析问题,比如环境问题,你的脚本可能在一个操作系统中工作,但在另一个操作系统中不工作,或者在一个虚拟环境中工作,但在另一个虚拟环境中不工作,或者在虚拟环境之外不工作。所有这些问题都可能是因为这两个环境有不同的解析器库可用。
建议了解或检查你当前工作环境中的默认解析器。你可以检查当前工作环境中可用的默认解析器,或者明确地将所需的解析器库作为第二个参数传递给BeautifulSoup构造函数。
不区分大小写
由于HTML标签和属性是不区分大小写的,所有三个HTML解析器都将标签和属性名称转换为小写。然而,如果你想保留混合大小写或大写的标签和属性,那么最好将文档解析为XML。
UnicodeEncodeError
让我们看看下面的代码段 –
soup = BeautifulSoup(response, "html.parser")
print (soup)
输出
UnicodeEncodeError: 'charmap' codec can't encode character '\u011f'
上述问题可能是由于两种主要情况。你可能试图打印出一个你的控制台不知道如何显示的unicode字符。第二,你试图写到一个文件,而你传入的Unicode字符不被你的默认编码所支持。
解决上述问题的一个方法是,在做汤之前对响应的文本/字符进行编码,以获得所需的结果,如下所示
responseTxt = response.text.encode('UTF-8')
KeyError: [attr]
它是由访问tag[‘attr’]引起的,而有关的标签没有定义attr属性。最常见的错误是:”KeyError: ‘href'” 和 “KeyError: ‘class'”。如果你不确定attr被定义,请使用tag.get(‘attr’)。
for item in soup.fetch('a'):
try:
if (item['href'].startswith('/') or "tutorialspoint" in item['href']):
(...)
except KeyError:
pass # or some other fallback action
属性错误(AttributeError)
你可能会遇到AttributeError,如下图所示
AttributeError: 'list' object has no attribute 'find_all'
上述错误的发生主要是因为你期望 find_all() 返回一个单一的标签或字符串。然而,soup.find_all 返回一个由元素组成的 python 列表。
你需要做的就是遍历这个列表并从这些元素中获取数据。