Beautiful Soup 故障排除
错误处理
BeautifulSoup需要处理的错误主要有两种。这两种错误不是来自你的脚本,而是来自代码片段的结构,因为BeautifulSoup API会抛出错误。
这两种主要的错误如下:
AttributeError
当点运算符在当前HTML标签中找不到兄弟标签时,会引发此错误。例如,你可能遇到了这个错误,因为缺少了“锚点标签”,cost-key在遍历时会引发错误,因为它需要一个锚点标签。
KeyError
如果需要的HTML标签属性缺失,会发生此错误。例如,如果片段中没有data-pid属性,pid键会引发键错误。
为了避免上述两种错误,在解析结果时,会绕过该结果以确保不会将格式不正确的片段插入数据库中。
except(AttributeError, KeyError) as er:
pass
diagnose()
每当我们在理解BeautifulSoup对我们的文档或HTML所做的操作方面遇到困难时,只需将其传递给测试()函数。通过将文档文件传递给测试()函数,我们可以展示不同解析器处理文档的列表。
以下是一个示例,演示了测试()函数的使用方法:
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: malformed start tag和HTMLParser.HTMLParserError: bad end tag,并且要解决这个问题,可以使用另一个主要解析器: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字符。
解决上述问题的一种方法是在创建BeautifulSoup对象之前对响应文本/字符进行编码,以获得所需的结果,如下所示−
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: 'list' object has no attribute 'find_all'
上述错误主要是因为您期望find_all()返回一个单独的标签或字符串。然而,soup.find_all返回一个Python元素的列表。
您只需要通过遍历列表并从这些元素中获取数据即可。