2015-04-10 9 views
16

Questo mi sta facendo impazzire, ho lottato per molte ore. Qualsiasi aiuto sarebbe molto apprezzato.Utilizzo di lxml per analizzare l'HTML con nome?

Sto usando PyQuery 1.2.9 (che è costruito sopra lxml) per racimolare this URL. Voglio solo ottenere un elenco di tutti i collegamenti nella sezione .linkoutlist.

Questa è la mia richiesta in piena:

response = requests.get('http://www.ncbi.nlm.nih.gov/pubmed/?term=The%20cost-effectiveness%20of%20mirtazapine%20versus%20paroxetine%20in%20treating%20people%20with%20depression%20in%20primary%20care') 
doc = pq(response.content) 
links = doc('#maincontent .linkoutlist a') 
print links 

Ma che restituisce un array vuoto. Se uso questa query invece:

links = doc('#maincontent .linkoutlist') 

allora ottengo questo ritorno questo HTML:

<div xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude" class="linkoutlist"> 
    <h4>Full Text Sources</h4> 
    <ul> 
     <li><a title="Full text at publisher's site" href="http://meta.wkhealth.com/pt/pt-core/template-journal/lwwgateway/media/landingpage.htm?issn=0268-1315&amp;volume=19&amp;issue=3&amp;spage=125" ref="itool=Abstract&amp;PrId=3159&amp;uid=15107654&amp;db=pubmed&amp;log$=linkoutlink&amp;nlmid=8609061" target="_blank">Lippincott Williams &amp; Wilkins</a></li> 
     <li><a href="http://ovidsp.ovid.com/ovidweb.cgi?T=JS&amp;PAGE=linkout&amp;SEARCH=15107654.ui" ref="itool=Abstract&amp;PrId=3682&amp;uid=15107654&amp;db=pubmed&amp;log$=linkoutlink&amp;nlmid=8609061" target="_blank">Ovid Technologies, Inc.</a></li> 
    </ul> 
    <h4>Other Literature Sources</h4> 
    ... 
</div> 

Così i selettori genitore restituiscono HTML con un sacco di <a> tags. Anche questo sembra essere un codice HTML valido.

Altri esperimenti rivelano che lxml non apprezza l'attributo xmlns sul div di apertura, per qualche motivo.

Come posso ignorarlo in lxml e analizzarlo come un normale HTML?

UPDATE: Cercando ns_clean, non riuscendo ancora:

parser = etree.XMLParser(ns_clean=True) 
    tree = etree.parse(StringIO(response.content), parser) 
    sel = CSSSelector('#maincontent .rprt_all a') 
    print sel(tree) 

risposta

6

È necessario gestire gli spazi dei nomi, incluso uno vuoto.

Soluzione di lavoro:

from pyquery import PyQuery as pq 
import requests 


response = requests.get('http://www.ncbi.nlm.nih.gov/pubmed/?term=The%20cost-effectiveness%20of%20mirtazapine%20versus%20paroxetine%20in%20treating%20people%20with%20depression%20in%20primary%20care') 

namespaces = {'xi': 'http://www.w3.org/2001/XInclude', 'test': 'http://www.w3.org/1999/xhtml'} 
links = pq('#maincontent .linkoutlist test|a', response.content, namespaces=namespaces) 
for link in links: 
    print link.attrib.get("title", "No title") 

Prints titoli di tutti i link corrispondenti al selettore:

Full text at publisher's site 
No title 
Free resource 
Free resource 
Free resource 
Free resource 

Oppure, semplicemente impostare il parser-"html" e dimenticare gli spazi dei nomi:

links = pq('#maincontent .linkoutlist a', response.content, parser="html") 
for link in links: 
    print link.attrib.get("title", "No title") 
+0

T Matassa così tanto. Interessato, puoi dirmi perché stavo vedendo questo spazio dei nomi collegato all'elemento 'div'? Non è lì nella fonte della pagina. – Richard

+1

@Richard ottima domanda che mi ha fatto pensare che gli spazi dei nomi sono stati inseriti da pyquery dal momento che ha cercato di analizzare il contenuto con parser xml, mentre necessario per farlo tramite parser html, si prega di consultare l'aggiornamento. Spero possa aiutare. – alecxe

+0

@alexce aha! grazie per la spiegazione. – Richard

0

Se mi ricordo bene di avere un problema simile me stesso qualche tempo fa. È possibile "ignora" lo spazio dei nomi con la mappatura a None in questo modo:

sel = CSSSelector('#maincontent .rprt_all a', namespaces={None: "http://www.w3.org/1999/xhtml"}) 
2

Buona fortuna per avere una standard XML/DOM Analizza per funzionare sulla maggior parte HTML. La soluzione migliore sarebbe utilizzare BeautifulSoup (pip install beautifulsoup4 o easy_install beautifulsoup4), che ha un sacco di gestione per le strutture costruite in modo errato. Forse qualcosa come questo, invece?

import requests 
from bs4 import BeautifulSoup 

response = requests.get('http://www.ncbi.nlm.nih.gov/pubmed/?term=The%20cost-effectiveness%20of%20mirtazapine%20versus%20paroxetine%20in%20treating%20people%20with%20depression%20in%20primary%20care') 
bs = BeautifulSoup(response.content) 
div = bs.find('div', class_='linkoutlist') 
links = [ a['href'] for a in div.find_all('a') ] 

>>> links 
['http://meta.wkhealth.com/pt/pt-core/template-journal/lwwgateway/media/landingpage.htm?issn=0268-1315&volume=19&issue=3&spage=125', 'http://ovidsp.ovid.com/ovidweb.cgi?T=JS&PAGE=linkout&SEARCH=15107654.ui', 'https://www.researchgate.net/publication/e/pm/15107654?ln_t=p&ln_o=linkout', 'http://www.diseaseinfosearch.org/result/2199', 'http://www.nlm.nih.gov/medlineplus/antidepressants.html', 'http://toxnet.nlm.nih.gov/cgi-bin/sis/search/r?dbs+hsdb:@[email protected]+24219-97-4'] 

io so che non è la libreria che cercavate da usare, ma mi hanno storicamente sbattuto la testa contro i muri in molte occasioni quando si tratta di DOM. I creatori di BeautifulSoup hanno aggirato molti casi limite che tendono ad accadere in natura.

Problemi correlati