【问题标题】:Data Scraping XPath span returns no value数据抓取 XPath 跨度不返回任何值
【发布时间】:2019-10-09 15:03:51
【问题描述】:

我正在尝试从在线评论网站检索有用性指标。使用 Python 和 lxml 我尝试检索此值,但输出仍然为空。我使用了以下代码和相应的 XPath:

span class="brand-find-useful__count">1</span>

tree = html.fromstring(page) helpfulness = tree.xpath('//span[@class="brand-find-useful__count"]/text()')

但是,它只是没有给我一个输出,只是一个空值。重要的是要注意,当没有竖起大拇指(有用)时,这个跨度不会出现。我在一个肯定有有用计数的页面上尝试了几次知道,但不幸的是我无法检索它。我仍然是新手,但我不知道错误是什么。

【问题讨论】:

  • tree.xpath('//span[@class="brand-find-useful__count"]/text()')返回一个列表,可以使用tree.xpath('//span[@class="brand-find-useful__count"]/text()')[0]获取文本。
  • 感谢您的快速回复。如果我这样做,我会得到:'IndexError: list index out of range'。
  • 嗨@Principia,欢迎来到 Stack Overflow! :-)。我不确定 XML 和网站。 HTML 不是 XML,这可能会给您带来一些问题。也许 Beautiful Soup 库更合适?它允许使用 CSS 选择器(riptutorial.com/python/example/4510/…)查询 HTML 树
  • 感谢@mhogerheijde 的欢迎和建议。我会仔细看看的。我从 xpath 方法开始并认为,也许有一种方法可以通过它来解决。将研究美丽的汤,谢谢。
  • 网址是什么?

标签: python html xpath web-scraping


【解决方案1】:

您使用了错误的 xpath//span[@class="brand-find-useful__count"]/text() 不是有效的 xpath,因为它仅在您有 JavaScript 渲染输出时才会出现。您可以通过查看浏览器中的页面源代码来验证这一点(不使用 devtools)

view-source:https://www.trustpilot.com/review/www.trivago.co.uk?page=4

您还可以在 view-source 中找到带有评论的 json 数据的脚本标签,您可以使用该 json 字符串而不是从元素中获取数据。我会把它留给你检查。

以下代码向您展示了如何从页面中获取帮助计数。

解决方案

import requests
from lxml import html

response = requests.get('https://www.trustpilot.com/review/www.trivago.co.uk?page=4')

tree = html.fromstring(response.text)

# fetches all useful elements 
useful = tree.xpath('//brand-find-useful-button')

# loop through each element
for e in useful:
  print(e.get(':initial-find-useful-count'))

输出

1
1
0
1
0
2
2
1
2
0
1
0
0
1
1
1
1
1
1

查看实际情况here

【讨论】:

  • 哇太棒了,这绝对有效!关于这个的一个小问题 - 虽然我确实在 Python 中看到了输出,但当我查看列表时,它显示的是“HtmlElement”而不是数字。我是否需要在脚本中添加一些内容以将值“HtmlElement”转换为相应的数字输出?从长远来看,我想在几页上运行脚本,然后附加它。
  • @Principia useful 是一个 HTMLElements 列表,因为属性值存在于我们不能只使用 text().text 的属性中。您可以将e.get(':initial-find-useful-count') 附加到列表以供以后使用。
【解决方案2】:

您也可以使用select,然后提取相关属性。

import requests
from bs4 import BeautifulSoup as bs

r = requests.get('https://www.trustpilot.com/review/www.trivago.co.uk?page=4')
soup = bs(r.content, 'lxml')

for review in soup.select('.review'):
    useful = review.select_one('brand-find-useful-button')
    print(useful[':initial-find-useful-count'])

【讨论】:

  • HTML 和 XML 都是常规语言。我建议反对使用正则表达式来解析HTML(或XML),因为你迟早会追逐无法解决的错误。
  • @mhogerheijde 我不是用正则表达式解析 html 本身。我正在解析一个字符串。我非常具体地确保我也在使用特定的字符串。 html 用 bs4 解析,节点匹配也是如此。
  • 您正在解释标签的字符串表示,对吧?在我的书中,这是解析。如果我错了,请纠正我,但str(useful) 的结果是<brand-find-useful-button :initial-find-use … d5f1">。正则表达式检查文本是否包含一些带有数值的属性。为什么不使用 BS 来获取属性及其值?
  • 最后一部分实际上是一个好点,我错过了,所以谢谢。已更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-19
  • 2021-10-15
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多