2012-02-23 33 views
5

Hialxml - khó phân tích cú pháp stackexchange rss feed

Tôi gặp sự cố khi phân tích cú pháp nguồn cấp dữ liệu rss từ stackexchange trong python. Khi tôi cố gắng nhận các nút tóm tắt, danh sách trống sẽ trả về

Tôi đã cố gắng giải quyết vấn đề này, nhưng không thể xoay đầu.

Có ai có thể giúp bạn không? nhờ một

In [3o]: import lxml.etree, urllib2

In [31]: url_cooking = 'http://cooking.stackexchange.com/feeds' 

In [32]: cooking_content = urllib2.urlopen(url_cooking) 

In [33]: cooking_parsed = lxml.etree.parse(cooking_content) 

In [34]: cooking_texts = cooking_parsed.xpath('.//feed/entry/summary') 

In [35]: cooking_texts 
Out[35]: [] 

Trả lời

9

Hãy nhìn vào hai phiên bản

import lxml.html, lxml.etree 

url_cooking = 'http://cooking.stackexchange.com/feeds' 

#lxml.etree version 
data = lxml.etree.parse(url_cooking) 
summary_nodes = data.xpath('.//feed/entry/summary') 
print('Found ' + str(len(summary_nodes)) + ' summary nodes') 

#lxml.html version 
data = lxml.html.parse(url_cooking) 
summary_nodes = data.xpath('.//feed/entry/summary') 
print('Found ' + str(len(summary_nodes)) + ' summary nodes') 

Như bạn khám phá, phiên bản thứ hai trả về không có các nút, nhưng phiên bản lxml.html hoạt động tốt. Phiên bản etree không hoạt động vì nó đang chờ các không gian tên và phiên bản html đang hoạt động vì nó bỏ qua các không gian tên. Một phần giảm xuống http://lxml.de/lxmlhtml.html, nó nói "Trình phân tích cú pháp HTML đáng chú ý bỏ qua các không gian tên và một số XMLisms khác".

Lưu ý khi bạn in nút gốc của phiên bản etree (print(data.getroot())), bạn sẽ nhận được một cái gì đó như <Element {http://www.w3.org/2005/Atom}feed at 0x22d1620>. Điều đó có nghĩa đó là yếu tố nguồn cấp dữ liệu có không gian tên là http://www.w3.org/2005/Atom. Đây là phiên bản sửa đổi của mã etree.

import lxml.html, lxml.etree 

url_cooking = 'http://cooking.stackexchange.com/feeds' 

ns = 'http://www.w3.org/2005/Atom' 
ns_map = {'ns': ns} 

data = lxml.etree.parse(url_cooking) 
summary_nodes = data.xpath('//ns:feed/ns:entry/ns:summary', namespaces=ns_map) 
print('Found ' + str(len(summary_nodes)) + ' summary nodes') 
+0

'data.xpath ('// ns: thức ăn chăn nuôi/ns: lối vào/ns: tóm tắt', namespace = { 'ns': 'http: //www.w3.org/2005/Atom '}) ' – reclosedev

+0

gah, không có gì lạ! Có vẻ như api đã đổi tên từ khóa 'namespaces' tại một số điểm. Cập nhật mẫu của tôi với mã làm việc. – gfortune

+0

cảm ơn bạn rất nhiều. Tôi sẽ bắt đầu kiểm tra thư mục gốc trước khi phân tích nó. – MrCastro

1

Hãy thử sử dụng BeautifulStoneSoup từ việc nhập khẩu beautifulsoup. Nó có thể làm các trick.

6

Sự cố là không gian tên.

Run này:

cooking_parsed.getroot().tag 

Và bạn sẽ thấy rằng nguyên tố này được namespaced như

{http://www.w3.org/2005/Atom}feed 

Tương tự, nếu bạn điều hướng đến một trong những mục thức ăn chăn nuôi.

này có nghĩa là xpath ngay trong lxml là:

print cooking_parsed.xpath(
    "//a:feed/a:entry", 
    namespaces={ 'a':'http://www.w3.org/2005/Atom' }) 
+0

Bằng cách nào đó tôi nghi ngờ câu trả lời này dễ hơn cho tôi. ;) Lừa đảo câu trả lời của bạn và cảm thấy tự do để chỉ ra bất kỳ lỗi nào tôi đã thực hiện trong tôi. – gfortune

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