2012-07-13 79 views
66

我使用BeautifulSoup湊一個網址,我有下面的代碼我們可以在BeautifulSoup中使用xpath嗎?

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'}) 

現在在上面的代碼中我們可以使用findAll獲得與之相關的標籤和信息,但我想使用XPath。是否有可能與BeautifulSoup一起使用xpath?如果可能的話,任何人都可以給我一個示例代碼,以便它更有幫助嗎?

回答

108

不,BeautifulSoup本身不支持XPath表達式。

另一個庫lxml,確實支持XPath 1.0。它有一個BeautifulSoup compatible mode它會嘗試和解析破碎的HTML湯方式。然而,default lxml HTML parser解析破碎的HTML的工作同樣出色,我相信速度更快。

將文檔解析爲lxml樹後,可以使用.xpath()方法搜索元素。

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) 

您可能感興趣的是CSS Selector support;在CSSSelector類轉化CSS語句轉換爲XPath表達式,使您的搜索td.empformbody容易得多:

from lxml.cssselect import CSSSelector 

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

一圈下來:BeautifulSoup本身確實有相當不錯CSS selector support

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

非常感謝Pieters,我從你的代碼中得到了兩個信息,1。一個澄清,我們不能與BS 2.使用xpath關於如何使用lxml一個很好的例子。我們能否在特定的文檔上看到它「我們無法以書面形式使用BS來實現xpath」,因爲我們應該向那些要​​求澄清權利的人展示一些證據? – 2012-07-13 08:01:16

+0

無論如何感謝你的preciuos幫助 – 2012-07-13 08:01:42

+6

很難證明一個消極的; [BeautifulSoup 4文檔](http://www.crummy.com/software/BeautifulSoup/bs4/doc/)具有搜索功能,並且沒有'xpath'的匹配。 – 2012-07-13 08:06:58

1

我搜遍了他們的docs,似乎沒有xpath選項。另外,你可以在SO上的類似問題上看到here,OP要求從xpath到BeautifulSoup的翻譯,所以我的結論是 - 不,沒有可用的xpath解析。

+0

['scrapy'(http://scrapy.org/)是另一種選擇,以獲得LXML工作機智BS實際上 – inspectorG4dget 2012-07-13 07:38:33

+0

是到現在爲止,我用它使用XPath來獲取裏面tags.Its數據scrapy非常方便和容易獲取數據,但我需要做到這一點與beautifulsoup相同,所以期待着它。 – 2012-07-13 07:46:48

77

我可以證實美麗的湯內沒有XPath支持。

+46

注意:Leonard Richardson是Beautiful Soup的作者,你會看到如果你點擊他的用戶資料。 – senshin 2014-05-14 05:30:37

+13

能夠在BeautifulSoup中使用XPATH將會非常好 – DarthOpto 2014-12-02 20:42:30

+0

那麼有什麼選擇呢? – 2017-05-08 11:04:22

9

BeautifulSoup有一個從當前元素命名爲findNext功能執導子女,所以:

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

上面的代碼可以模仿以下XPath:

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

的Martijn的代碼不再正常工作(這是4 +歲以前......),則etree.parse()行將打印到控制檯,並且不會將值分配給tree變量。引用this,我能弄清楚這個工程使用要求和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

這是一個非常古老的線程,但有一個變通的解決方案,現在,這可能不是一直在BeautifulSoup的時候。

這是我做的一個例子。我使用「requests」模塊來讀取RSS提要,並在名爲「rss_text」的變量中獲取其文本內容。這樣,我通過BeautifulSoup運行它,搜索xpath/rss/channel/title並檢索其內容。它不完全是XPath的所有榮耀(通配符,多條路徑等),但是如果你只有一條你想要找到的基本路徑,它就可以工作。

from bs4 import BeautifulSoup 
rss_obj = BeautifulSoup(rss_text, 'xml') 
cls.title = rss_obj.rss.channel.title.get_text() 
相關問題