2012-07-13 42 views
66

Tôi đang sử dụng BeautifulSoup để cạo một url và tôi đã có đoạn mã sauchúng ta có thể sử dụng xpath với BeautifulSoup không?

import urllib 
import urllib2 
from BeautifulSoup import BeautifulSoup 

url = "http://www.example.com/servlet/av/ResultTemplate=AVResult.html" 
req = urllib2.Request(url) 
response = urllib2.urlopen(req) 
the_page = response.read() 
soup = BeautifulSoup(the_page) 
soup.findAll('td',attrs={'class':'empformbody'}) 

Bây giờ trong đoạn code trên chúng ta có thể sử dụng findAll để có được thẻ và thông tin liên quan đến họ, nhưng tôi muốn sử dụng xpath. Có thể sử dụng xpath với BeautifulSoup không? Nếu có thể, bất cứ ai có thể vui lòng cung cấp cho tôi một mã ví dụ để nó có hữu ích hơn không?

Trả lời

108

Không, chính BeautifulSoup không hỗ trợ các biểu thức XPath.

Thư viện thay thế, lxml, không hỗ trợ XPath 1.0. Nó có một số BeautifulSoup compatible mode nơi nó sẽ thử và phân tích cú pháp HTML bị hỏng theo cách thức của Soup. Tuy nhiên, các default lxml HTML parser không chỉ là một công việc tốt của phân tích cú pháp HTML bị hỏng, và tôi tin là nhanh hơn.

Khi bạn đã phân tích cú pháp tài liệu của mình thành cây lxml, bạn có thể sử dụng phương thức .xpath() để tìm kiếm các phần tử.

import urllib2 
from lxml import etree 

url = "http://www.example.com/servlet/av/ResultTemplate=AVResult.html" 
response = urllib2.urlopen(url) 
htmlparser = etree.HTMLParser() 
tree = etree.parse(response, htmlparser) 
tree.xpath(xpathselector) 

Có thể bạn quan tâm là CSS Selector support; lớp CSSSelector dịch báo cáo CSS vào các biểu thức XPath, làm cho tìm kiếm của bạn cho td.empformbody rằng có rất nhiều dễ dàng hơn:

from lxml.cssselect import CSSSelector 

td_empformbody = CSSSelector('td.empformbody') 
for elem in td_empformbody(tree): 
    # Do something with these table cells. 

Coming vòng tròn đầy đủ: BeautifulSoup tự không có khá tốt CSS selector support:

for cell in soup.select('table#foobar td.empformbody'): 
    # Do something with these table cells. 
+0

Cảm ơn Pieters rất nhiều, tôi có hai thông tin từ mã ur, 1. Một làm rõ rằng chúng tôi không thể sử dụng xpath với BS 2.A ví dụ tốt đẹp về cách sử dụng lxml. Chúng ta có thể thấy nó trên một tài liệu cụ thể rằng "chúng ta không thể thực hiện xpath bằng BS dưới dạng văn bản", bởi vì chúng ta nên trình bày một số bằng chứng cho những người yêu cầu làm rõ đúng không? –

+0

Dù sao, xin cảm ơn sự giúp đỡ của quý vị trước số –

+6

Thật khó để chứng minh một tiêu cực; tài liệu [BeautifulSoup 4] (http://www.crummy.com/software/BeautifulSoup/bs4/doc/) có chức năng tìm kiếm và không có lần truy cập nào cho 'xpath'. –

1

Tôi đã tìm kiếm qua docs và dường như không có tùy chọn xpath. Ngoài ra, bạn có thể thấy here về một câu hỏi tương tự trên SO, OP yêu cầu bản dịch từ xpath sang BeautifulSoup, vì vậy kết luận của tôi sẽ là - không, không có phân tích xpath nào khả dụng.

+0

[ 'scrapy'] (http://scrapy.org/) là một tùy chọn để có được lxml làm việc wit BS – inspectorG4dget

+0

có thực sự đến bây giờ tôi sử dụng scrapy trong đó sử dụng xpath để lấy dữ liệu bên trong tags.Its rất tiện dụng và dễ dàng để tìm nạp dữ liệu, nhưng tôi có một nhu cầu để làm điều tương tự với beautifulsoup vì vậy mong muốn vào nó. –

77

Tôi có thể khẳng định rằng không có hỗ trợ XPath trong Beautiful Soup.

+46

Lưu ý: Leonard Richardson là tác giả của Beautiful Soup, vì bạn sẽ thấy nếu bạn nhấp qua hồ sơ người dùng của mình. – senshin

+13

Sẽ rất tuyệt khi có thể sử dụng XPATH trong BeautifulSoup – DarthOpto

+0

Vậy giải pháp thay thế là gì? –

9

BeautifulSoup có một hàm có tên findNext từ yếu tố hiện tại đạo diễn childern, vì vậy:

father.findNext('div',{'class':'class_value'}).findNext('div',{'id':'id_value'}).findAll('a') 

Trên mã có thể bắt chước các xpath sau:

div[class=class_value]/div[id=id_value] 
16

đang Martijn của không còn hoạt động đúng (nó là 4 + năm tuổi bây giờ ...), các dòng in etree.parse() in bảng điều khiển và không gán giá trị cho biến số tree. Tham khảo this, tôi đã có thể hình dung ra công trình này sử dụng các yêu cầu và lxml:

from lxml import html 
import requests 

page = requests.get('http://econpy.pythonanywhere.com/ex/001.html') 
tree = html.fromstring(page.content) 
#This will create a list of buyers: 
buyers = tree.xpath('//div[@title="buyer-name"]/text()') 
#This will create a list of prices 
prices = tree.xpath('//span[@class="item-price"]/text()') 

print 'Buyers: ', buyers 
print 'Prices: ', prices 
0

Đây là một chủ đề khá cũ, nhưng có một công việc xung quanh giải pháp bây giờ, có thể không có được trong BeautifulSoup vào thời điểm đó .

Dưới đây là ví dụ về những gì tôi đã làm. Tôi sử dụng mô-đun "yêu cầu" để đọc nguồn cấp dữ liệu RSS và nhận nội dung văn bản của nó trong một biến được gọi là "rss_text". Cùng với đó, tôi chạy nó qua BeautifulSoup, tìm kiếm xpath/rss/channel/title và truy xuất nội dung của nó. Nó không chính xác là XPath trong tất cả vinh quang của nó (các ký tự đại diện, nhiều đường dẫn, v.v.), nhưng nếu bạn chỉ có một con đường cơ bản mà bạn muốn định vị, thì nó hoạt động.

from bs4 import BeautifulSoup 
rss_obj = BeautifulSoup(rss_text, 'xml') 
cls.title = rss_obj.rss.channel.title.get_text() 
Các vấn đề liên quan