2015-04-10 20 views
16

Điều này khiến tôi hoàn toàn điên loạn, tôi đã phải vật lộn với nó trong nhiều giờ. Bất kì sự trợ giúp nào đều được đánh giá cao.Sử dụng lxml để phân tích cú pháp tên HTML?

Tôi đang sử dụng PyQuery 1.2.9 (được xây dựng trên đầu trang của lxml) để cạo this URL. Tôi chỉ muốn có danh sách tất cả các liên kết trong phần .linkoutlist.

Đây là yêu cầu của tôi đầy đủ:

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 

Nhưng đó trả về một mảng trống. Nếu tôi sử dụng truy vấn này để thay thế:

links = doc('#maincontent .linkoutlist') 

Sau đó, tôi quay trở lại này HTML này:

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

Vì vậy, các bộ chọn cha mẹ làm trở HTML với nhiều <a> thẻ. Đây cũng có vẻ là HTML hợp lệ.

Thử nghiệm khác cho thấy lxml không thích thuộc tính xmlns trên div mở, vì một lý do nào đó.

Tôi làm cách nào để bỏ qua điều này trong lxml và phân tích cú pháp như HTML thông thường?

CẬP NHẬT: Đang cố gắng ns_clean, vẫn thất bại:

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

Trả lời

6

Bạn cần phải xử lý các không gian tên, bao gồm cả vùng trống.

giải pháp làm việc:

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") 

In tiêu đề của tất cả các liên kết khớp với bộ chọn:

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

Hoặc, chỉ cần đặt các parser-"html" và quên đi không gian tên:

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

T hanks rất nhiều. Không quan tâm, bạn có thể cho tôi biết tại sao tôi đã nhìn thấy không gian tên này gắn liền với phần tử 'div'? Nó không có trong nguồn của trang. – Richard

+1

@Richard câu hỏi tuyệt vời mà làm cho tôi nghĩ rằng không gian tên đã được chèn bởi pyquery kể từ khi nó đã cố gắng phân tích cú pháp nội dung với xml phân tích cú pháp, trong khi cần thiết để làm điều đó thông qua html parser, xin vui lòng xem bản cập nhật. Hy vọng rằng sẽ giúp. – alecxe

+0

@alexce aha! cám ơn vì đã giải thích. – Richard

0

Nếu tôi nhớ chính xác từ việc có một vấn đề tương tự bản thân mình một thời gian trước đây. Bạn có thể "bỏ qua" không gian tên bằng cách ánh xạ nó vào None như thế này:

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

Chúc may mắn nhận được một XML tiêu chuẩn/DOM phân tích để làm việc trên hầu hết các mã HTML. Đặt cược tốt nhất của bạn sẽ là sử dụng BeautifulSoup (pip install beautifulsoup4 hoặc easy_install beautifulsoup4), trong đó có rất nhiều xử lý cho các cấu trúc được xây dựng không chính xác. Có lẽ một cái gì đó như thế này thay thế?

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

Tôi biết đó không phải là thư viện bạn đang sử dụng, nhưng trước đây tôi đã đập vào tường nhiều lần khi nói đến DOM. Những người sáng tạo của BeautifulSoup đã phá vỡ nhiều trường hợp cạnh có xu hướng xảy ra trong tự nhiên.

Các vấn đề liên quan