我不想知道如何解决这个问题,因为我已经自己解决了。我只是问它是否真的是一个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>3=7">nomeLink</a>'
p = MyParser()
p.feed(s)
输出如下:
"/home?ID=123>3=7"
不,这不是一个bug。您正在向解析器提供无效的HTML,在HTML属性的URL中包含&
的正确方法是将其转义为&
:
>>> s = '<a href="/home?ID=123&gt3=7">nomeLink</a>'
>>> p = MyParser()
>>> p.feed(s)
/home?ID=123>3=7
解析器尽了最大努力(按照HTML标准的要求),并尽其所能为您提供"修复"的数据。在这种情况下,它试图修复另一个常见的HTML错误:将>
拼写为>
(忘记了;
分号)。
我建议您使用BeautifulSoup,而不是自己构建在(相当低级的)html.parser
库之上。BeautifulSoup支持多个解析器,其中一些解析器可以比其他解析器更好地处理损坏的HTML。
例如,与html.parser
相比,html5lib
解析器可以更好地处理属性中未标注的与号:
>>> from bs4 import BeautifulSoup
>>> s = '<a href="/home?ID=123>3=7">nomeLink</a>'
>>> BeautifulSoup(s, 'html.parser').find('a')['href']
'/home?ID=123>3=7'
>>> BeautifulSoup(s, 'html5lib').find('a')['href']
'/home?ID=123>3=7'
为了完整起见,第三个受支持的解析器lxml
也像转义符一样处理未转义的符号:
>>> BeautifulSoup(s, 'lxml').find('a')['href']
'/home?ID=123>3=7'
你可以直接使用lxml
和html5lib
,但你会放弃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行