如何通过 Nokogiri 在页面上获取特定的可查看字符串

Posted

技术标签:

【中文标题】如何通过 Nokogiri 在页面上获取特定的可查看字符串【英文标题】:How to get a specific viewable string on page through Nokogiri 【发布时间】:2020-09-01 10:55:30 【问题描述】:

目前,我能够使用 Nokogiri 解析网站并从页面中获取特定元素。但是,我需要能够获取用户可见的特定字符串,例如“Out of stock”:

page.text.match('Out of stock') 

这对于获取正确的字符串并在字符串存在或不存在时返回 true 或 false 非常有效,但是,如下所示的某些链接即使项目没有缺货也会返回 true,因为该特定字符串是隐藏在页面上的脚本标签中:

https://www.walmart.com/ip/Funyuns-Onion-Flavored-Rings-6-oz/36915849?athcpid=36915849&athpgid=athenaItemPage&athcgid=null&athznid=PWSFM&athieid=v0&athstid=CS020&athguid=ba634528-888-172187cc96a580&athancid=null&athena=true

我正在寻找一种方法,以便当且仅当它对用户可见时才会拉出该字符串,因此上面应该返回 false 以匹配“缺货”字符串,而下面的链接应该返回 true(有时发布),因为该项目实际上是缺货。

https://www.walmart.com/ip/4-Pack-Chesters-Flamin-Hot-Popcorn-4-25-oz/737202470?selected=true

我也知道我可以获取包含字符串的特定标签,但我需要监控数百个网站,因此解决方案必须是广泛搜索可见字符串。

【问题讨论】:

页面抓取是出了名的不可靠,尤其是当你试图让它在数百个网站上运行时。作为开始,您可以尝试包含前面的 > 和后面的 < 字符的正则表达式搜索。但是,虽然它可能会有所帮助,但这绝不是万无一失的。我也会看看 Capybara ......它可能不是特别性能,但它可能会更可靠。 “可见”有时也很难指定。如果它在脚本中,它显然是不可见的。如果它有 style="display: none",那么它也可能不可见。但是,如果它是白色背景上的白色怎么办。如果它在其他东西后面怎么办,如果它位于页面之外怎么办,如果它的字体大小是微观的怎么办? 您必须做一些比搜索短文本字符串更具体和准确的事情;太容易上当了。当与数百个站点一起工作时,很有可能您必须编写数百个爬虫,因为每个站点对页面的代码都不同。尽可能利用对其站点的 REST 或 API 调用,因为您获得的数据将更容易处理且更可靠。 如果没有 API,你真的应该问问自己,你所做的是否违反了 TOS。 【参考方案1】:

简短的回答:我们可以使用更具体的xpath 语法。

长篇大论: 我强烈建议更具体地使用 css-classes,因为在某些情况下,我们不仅可以在“脚本标签”中获取此文本,还可以通过媒体查询或项目预览块或其他方式获取此文本,并将常见情况处理为大块,但不要强制在所有情况下都使用一种特定的解决方案,以防出现意外行为

所以我们需要更具体一些,使用“target-tags”来处理,例如:

Nokogiri::html.parse(page.html).xpath("//*[contains(@class, 'prod-PriceSection')]//*[contains(@class, 'prod-ProductOffer-oosMsg')]").text
"Out of stock"

所以,“监控数百个网站”我们可以采用这种方法:

xpath("//*[contains(@class, 'PriceSection')]").text

或者甚至更好地使用这样的东西来确保元素清晰可见:

page.all("//body//*[contains(text(), 'Out of stock')]", visible: true).count
# => 1

如果 Capybara 使用更多请求(在以前的解决方案中)可能会成为问题,我们可以使用此解决方案,它会更快:

xpath("//body//*[not(self::script) and contains(text(), 'Out of stock')]").count

希望对你有帮助

【讨论】:

如果网站使用 CSS 或 DHTML 以编程方式隐藏或显示“缺货”字符串,这将无法正常工作。 Nokogiri 不知道页面的状态,它只知道标记包含的内容。在命令行使用nokogiri 加载页面并查看DOM;它只适用于静态页面。 优秀。那个底部的例子效果很好。非常感谢!

以上是关于如何通过 Nokogiri 在页面上获取特定的可查看字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Nokogiri 获取没有任何文本内容的完整 HTML

如何在 Mac OS Sierra 10.12 上安装 Nokogiri

无法在 Ruby 版本高于要求的 CentOS 上安装 Nokogiri

使用Savon和Nokogiri在Rails中解析XML SOAP响应的内存不足

如何在Docker上设置ruby - 得到nokogiri错误

如何使用 Nokogiri 解析 HTML 表格?