HTMLParser неправильно понимает объекты в href. Это ошибка или нет? Должен ли я сообщить об этом?

Я не хочу знать, как решить проблему, потому что я решил ее самостоятельно. Я просто спрашиваю, действительно ли это ошибка, и как я должен сообщить об этом. Вы можете найти код и вывод ниже:

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) 

Ниже приведен вывод:

"/ Дом? ID = 123> 3 = 7"

Нет, это не ошибка. Вы загружаете недействительный HTML-код парсера, правильный способ включить & в URL-адрес в атрибуте HTML состоит в том, чтобы убедить его в &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 ; забывая точку с запятой).

Вместо того, чтобы самостоятельно html.parser (довольно низкоуровневую) библиотеку html.parser , я рекомендую вместо этого использовать BeautifulSoup . BeautifulSoup поддерживает несколько парсеров, и некоторые из них могут обрабатывать разбитый HTML лучше, чем другие.

Например, парсер html5lib может обрабатывать неэксклюзивные амперсанды в атрибутах лучше, чем html.parser может:

 >>> 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' 

Вы можете использовать lxml и html5lib напрямую, но тогда вы отказываетесь от хорошего API высокого уровня, который предлагает BeautifulSoup.

Python 3.3.2 (v3.3.2, 16 мая 2013, 00:03:43) [MSC v.1600 32 бит (Intel)] на win32

Пусть feed s = '<pa = "& # 39;"> в MyHTMLParser:

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

Это действительный тег html, где & # 39; для '. В этом случае MyHTMLParser дает для attrs:

 [('a', "'")] 

Причиной такого результата является использование функции unescape:

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

где self.unescape является внутренним помощником для удаления специальных котировок символов, который используется только для значений атрибутов. См. Строки 504-532 в parser.py.