BeautifulSoup 教程, 本文介绍BeautifulSoup的异常处理。
异常处理
在BeautifulSoup中,有两种主要的错误需要处理。这两种错误不是来自于你的脚本,而是来自于片段的结构,因为BeautifulSoup的API会抛出一个错误.
两个主要错误如下 −
AttributeError
它是在点符号没有找到当前HTML标签的同级标签时引起的。例如,你可能遇到过这样的错误,因为缺少 "锚标签",cost-key会在遍历时抛出一个错误,需要一个锚标签.
KeyError
如果缺少所需的HTML标签属性,就会发生这个错误。例如,如果我们在一个片段中没有data-pid属性,pid键将抛出key-error.
为了避免在解析一个结果时出现上述两个列举的错误,该结果将被绕过,以确保一个畸形的片段不会被插入数据库中 −
except(AttributeError, KeyError) as er:
pass
diagnose()
每当我们发现在理解BeautifulSoup对我们的文档或HTML所做的任何困难时,只需将其传递给diagnose()函数。在将文档文件传递给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列表.
你所需要做的就是在列表中进行迭代,并从这些元素中抓取数据.