2009-11-23 3 views
9

Sto tentando di analizzare e inviare un modulo su un sito Web utilizzando mechanize, ma sembra che il parser del modulo incorporato non possa rilevare il modulo e i suoi elementi. Sospetto che stia soffocando su HTML mal formato, e mi piacerebbe provare ad analizzarlo con un parser meglio progettato per gestire HTML non valido (ad esempio lxml o BeautifulSoup) e quindi alimentare l'output prettificato e ripulito nel modulo parser. Ho bisogno di meccanizzare non solo per inviare il modulo ma anche per mantenere le sessioni (sto lavorando su questo modulo da una sessione di login.)È possibile collegare un parser HTML più robusto a Python mechanize?

Non sono sicuro di come procedere, se è effettivamente possibile. Non sono così familiare con i vari dettagli del protocollo HTTP, su come far lavorare insieme le varie parti ecc.

risposta

3

lettura dalla grande esempio sulla prima pagina del mechanize website:

# Sometimes it's useful to process bad headers or bad HTML: 
response = br.response() # this is a copy of response 
headers = response.info() # currently, this is a mimetools.Message 
headers["Content-type"] = "text/html; charset=utf-8" 
response.set_data(response.get_data().replace("<!---", "<!--")) 
br.set_response(response) 

così sembra molto possibile pre-elaborazione della risposta con un altro parser che rigenerare ben formato HTML, quindi alimentare però meccanizzare per ulteriore elaborazione.

+0

Sì, lo Credo di essermi perso. Poi di nuovo, i documenti di meccanizzazione non sono esattamente i migliori organizzati intorno. Grazie! – int3

1

Cosa stai cercando può essere fatto con lxml.etree che è la xml.etree.ElementTree emulatore (e sostituzione) fornita da lxml:

Prima prendiamo cattivo mal-formato HTML:

% cat bad.html 
<html> 
<HEAD> 
    <TITLE>this HTML is awful</title> 
</head> 
<body> 
    <h1>THIS IS H1</H1> 
    <A HREF=MYLINK.HTML>This is a link and it is awful</a> 
    <img src=yay.gif> 
</body> 
</html> 

(Osservare il caso misto tra tag di apertura e chiusura, virgolette mancanti).

E poi analizzarlo:

>>> from lxml import etree 
>>> bad = file('bad.html').read() 
>>> html = etree.HTML(bad) 
>>> print etree.tostring(html) 
<html><head><title>this HTML is awful</title></head><body> 
    <h1>THIS IS H1</h1> 
    <a href="MYLINK.HTML">This is a link and it is awful</a> 
    <img src="yay.gif"/></body></html> 

osservare che la codifica e la quotazione è stato corretto per noi.

Se si verificano problemi durante l'analisi dell'HTML, questa potrebbe essere la risposta che si sta cercando. Per quanto riguarda i dettagli di HTTP, questa è un'altra questione.

+0

So come usare lxml, in realtà ..: P Mi stavo chiedendo come farlo funzionare con mechanize. – int3

+0

Allora buona fortuna a te allora! Afferra le tue caviglie! – jathanism

10

Ho avuto un problema in cui mancava un campo modulo da un modulo, non sono riuscito a trovare alcun html malformato ma ho pensato che fosse la causa quindi ho usato la funzione di prettifica di BeautifulSoup per analizzarlo e ha funzionato.

resp = br.open(url) 
soup = BeautifulSoup(resp.get_data()) 
resp.set_data(soup.prettify()) 
br.set_response(resp) 

Mi piacerebbe sapere come farlo automaticamente.

Edit: scoperto come fare questo automaticamente

class PrettifyHandler(mechanize.BaseHandler): 
    def http_response(self, request, response): 
     if not hasattr(response, "seek"): 
      response = mechanize.response_seek_wrapper(response) 
     # only use BeautifulSoup if response is html 
     if response.info().dict.has_key('content-type') and ('html' in response.info().dict['content-type']): 
      soup = BeautifulSoup(response.get_data()) 
      response.set_data(soup.prettify()) 
     return response 

    # also parse https in the same way 
    https_response = http_response 

br = mechanize.Browser() 
br.add_handler(PrettifyHandler()) 

br sarà ora possibile utilizzare BeautifulSoup per analizzare tutte le risposte in cui HTML è contenuta nel tipo di contenuto (tipo MIME), ad esempio text/html

+0

Hai testato la soluzione aggiornata ('PrettifyHandler')? Non ha funzionato per me. – sirfz

+0

@sirfz L'ho provato al momento e ha funzionato. Non ho usato mechanize o BeautifulSoup per diversi anni, forse non funziona con le versioni attuali. Sei sicuro che la tua risposta abbia un'intestazione 'content-type' che includa la stringa' html'? – cerberos

+0

sì ho aggiunto un pdb all'interno di 'http_response' prima della condizione e non l'ha mai raggiunto. Immagino che sia come hai detto tu, non compatibile con l'ultima versione anche se sarebbe stato molto conveniente. – sirfz