HTMLParser误解了href中的实体.这是不是一个bug?我应该报告吗



我不想知道如何解决这个问题,因为我已经自己解决了。我只是问它是否真的是一个bug,以及我是否应该以及如何报告它。您可以在下面找到代码和输出:

from html.parser import HTMLParser
class MyParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        for at in attrs:
            if at[0] == 'href':
                print(at[1])
        return super().handle_starttag(tag, attrs)
    def handle_data(self, data):
        return super().handle_data(data)
    def handle_endtag(self, tag):
        return super().handle_endtag(tag)

s = '<a href="/home?ID=123&gt3=7">nomeLink</a>'
p = MyParser()
p.feed(s)

输出如下:

"/home?ID=123>3=7"

不,这不是一个bug。您正在向解析器提供无效的HTML,在HTML属性的URL中包含&的正确方法是将其转义为&amp;:

>>> s = '<a href="/home?ID=123&amp;gt3=7">nomeLink</a>'
>>> p = MyParser()
>>> p.feed(s)
/home?ID=123&gt3=7

解析器尽了最大努力(按照HTML标准的要求),并尽其所能为您提供"修复"的数据。在这种情况下,它试图修复另一个常见的HTML错误:将&gt;拼写为&gt(忘记了;分号)。

我建议您使用BeautifulSoup,而不是自己构建在(相当低级的)html.parser库之上。BeautifulSoup支持多个解析器,其中一些解析器可以比其他解析器更好地处理损坏的HTML。

例如,与html.parser相比,html5lib解析器可以更好地处理属性中未标注的与号:

>>> from bs4 import BeautifulSoup
>>> s = '<a href="/home?ID=123&gt3=7">nomeLink</a>'
>>> BeautifulSoup(s, 'html.parser').find('a')['href']
'/home?ID=123>3=7'
>>> BeautifulSoup(s, 'html5lib').find('a')['href']
'/home?ID=123&gt3=7'

为了完整起见,第三个受支持的解析器lxml也像转义符一样处理未转义的符号:

>>> BeautifulSoup(s, 'lxml').find('a')['href']
'/home?ID=123&gt3=7'

你可以直接使用lxmlhtml5lib,但你会放弃BeautifulSoup提供的高级API。

Python 3.3.2(v3.3.2,2013年5月16日,00:03:43)[MSC v.1600 32位(英特尔)]在win32 上

让提要s='<p a="';">'到MyHTMLParser:

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        print(attrs)

这是有效的html标记,其中&39;用于"。在这种情况下,MyHTMLParser为属性提供:

[('a', "'")]

出现这种结果的原因是使用了unescape函数:

Lines in source file html/parser.py, class HTMLParser
348:            if attrvalue:
349:                attrvalue = self.unescape(attrvalue)

其中self.unescape是一个内部帮助程序,用于删除特殊字符引用,仅用于属性值。请参阅parser.py.中的第504-532行

最新更新