HTMLParser fraintende le quadro in href. È un bug o no? Dovrei segnalarlo?

Non voglio sapere come risolvere il problema, perché l’ho risolto da solo. Sto solo chiedendo se è davvero un bug e se e come dovrei segnalarlo. Puoi trovare il codice e l’output qui sotto:

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 = 'nomeLink' p = MyParser() p.feed(s) 

Quello che segue è l’output:

“/ Home? ID = 123> 3 = 7”

No, non è un bug. Stai inviando il parser HTML non valido, il modo corretto per includere & in un URL in un attributo HTML è di sfuggire a & :

 >>> s = 'nomeLink' >>> p = MyParser() >>> p.feed(s) https://stackoverflow.com/home?ID=123&gt3=7 

Il parser ha fatto del suo meglio (come richiesto dallo standard HTML) e ti ha dato dati “riparati” al meglio delle sue capacità. In questo caso, ha provato a riparare un altro errore HTML non funzionante: ortografia > come &gt (dimenticando il ; punto ; virgola).

Invece di creare da soli la libreria html.parser (piuttosto di basso livello), ti consiglio di utilizzare BeautifulSoup . BeautifulSoup supporta più parser e alcuni di questi possono gestire l’HTML spezzato meglio di altri.

Ad esempio, il parser html5lib grado di gestire e commerciali con caratteri senza html.parser negli attributi meglio di html.parser può:

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

Per completezza, il terzo parser supportato, lxml , gestisce anche e commerciali senza escape come se fossero fuggiti:

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

È ansible utilizzare direttamente lxml e html5lib , ma poi si rinuncia alla buona API di alto livello offerta da BeautifulSoup.

Python 3.3.2 (v3.3.2, 16 maggio 2013, 00:03:43) [MSC v.1600 32 bit (Intel)] su win32

Consenti feed s = ‘ “a MyHTMLParser:

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

Questo è un tag html valido dove & # 39; è per ‘. In questo caso MyHTMLParser fornisce per attrs:

 [('a', "'")] 

La ragione di tale risultato è l’uso della funzione unescape:

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

dove self.unescape è un helper interno per rimuovere la citazione di caratteri speciali, che viene utilizzata solo per i valori degli attributi. Vedi le linee 504-532 in parser.py.