7 题: 我们可以在BeautifulSoup中使用xpath吗?

在...创建的问题 Wed, Dec 20, 2017 12:00 AM

我正在使用BeautifulSoup来抓取一个网址,我有以下代码

 
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。是否可以将xpath与BeautifulSoup一起使用?如果可能,有人可以提供一个示例代码,以便更有帮助吗?

    
88
7答案                              7 跨度>                         

Nope,BeautifulSoup本身不支持XPath表达式。

另一个库, lxml 支持XPath 1.0。它有一个 BeautifulSoup兼容模式,它会像Soup一样尝试解析破碎的HTML。但是,默认的lxml HTML解析器在解析损坏的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支持; 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选择器支持

 
for cell in soup.select('table#foobar td.empformbody'):
    # Do something with these table cells.
    
140
2019-02-09 10:32:54Z
  1. 非常感谢Pieters,我从你的代码得到了两个信息,1。澄清我们不能使用xpath与BS 2.一个关于如何使用lxml的一个很好的例子。我们是否可以在特定文档中看到“我们无法以书面形式使用BS实现xpath”,因为我们应该向那些要​​求澄清的人展示一些证据吗?
    2012-07-13 08:01:16Z
  2. 无论如何,谢谢你的帮助
    2012-07-13 08:01:42Z
  3. 很难证明是消极的; BeautifulSoup 4文档具有搜索功能,没有点击'的xpath”。
    2012-07-13 08:06:58Z
  4. 哦k Pieters再次感谢!!!!
    2012-07-13 08:40:25Z
  5. 醇>

我可以确认Beautiful Soup中没有XPath支持。

    
93
2012-07-13 11:44:45Z
  1. 注意:Leonard Richardson是Beautiful Soup的作者,您将看到是否点击了他的用户个人资料。
    2014-05-14 05:30:37Z
  2. 能够在BeautifulSoup中使用XPATH是非常好的
    2014-12-02 20:42:30Z
  3. 那么替代方案是什么?
    2017-05-08 11:04:22Z
  4. 醇>

Martijn的代码不再正常运行(现在已经4年多了......),etree.parse()行打印到控制台,不会将值分配给tree变量。参考这个,我能够使用请求和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
    
34
2017-01-06 21:38:07Z
  1. 一个警告:我注意到根目录外是否有东西(如外部< html>标记之外的\n),然后根目录引用xpaths不起作用,你必须使用相对xpath。 lxml.de/xpathxslt.html
    2018-09-06 13:38:41Z
  2. 醇>

BeautifulSoup有一个名为 findNext 来自当前元素导向的childern,所以:

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

上面的代码可以模仿以下xpath:

 
div[class=class_value]/div[id=id_value]
    
12
2017-02-03 19:21:31Z

我搜索了他们的文档,似乎有不是xpath选项。此外,您可以在类似的地方看到此处关于SO的问题,OP要求从xpath到BeautifulSoup的转换,所以我的结论是 - 不,没有可用的xpath解析。

    
1
2017-05-23 10:31:31Z
  1. scrapy 是让lxml工作的另一个选择BS
    2012-07-13 07:38:33Z
  2. 是的,直到现在我使用了scrapy,它使用xpath来获取tags内的数据。它非常方便且易于获取数据,但我需要做同样的事情与beautifulsoup如此期待它。
    2012-07-13 07:46:48Z
  3. 醇>

当你使用lxml时简单:

 
tree = lxml.html.fromstring(html)
i_need_element = tree.xpath('//a[@class="shared-components"]/@href')

但是当使用BeautifulSoup BS4时也很简单:

  • 首先删除“//”和“@”
  • 秒 - 在“=”
  • 之前添加星标

试试这个魔法:

 
soup = BeautifulSoup(html, "lxml")
i_need_element = soup.select ('a[class*="shared-components"]')

如您所见,这不支持子标记,因此我删除了“/@ href”部分

    
1
2018-08-18 10:15:26Z

这是一个非常古老的主题,但现在有一个解决方案,当时可能没有在BeautifulSoup中。

以下是我所做的一个例子。我使用“请求”模块来读取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()
    
0
2017-12-15 21:46:08Z
  1. 我相信这只会找到子元素。 XPath是另一回事吗?
    2019-01-03 15:34:02Z
  2. 醇>
来源放置 这里