【问题标题】:How do I scrape data from a page that loads specific data after the main page load?如何在主页加载后从加载特定数据的页面中抓取数据?
【发布时间】:2012-07-17 15:17:05
【问题描述】:

我一直在使用 Ruby 和 Nokogiri 从一个类似于 hollister 网站的 URL 中提取数据:http://www.hollisterco.com/webapp/wcs/stores/servlet/TrackDetail?storeId=10251&catalogId=10201&langId=-1&URL=TrackDetailView&orderNumber=1316358

我的脚本现在看起来像这样:

require 'rubygems'
require 'nokogiri'
require 'open-uri'

page = Nokogiri::HTML(open("http://www.hollisterco.com/webapp/wcs/stores/servlet/TrackDetail?storeId=10251&catalogId=10201&langId=-1&URL=TrackDetailView&orderNumber=1316358")) 

puts page.css("h3[data-property=GLB_ORDERNUMBERSYMBOL]")[0].text

我的问题是 Hollister 页面有某种异步加载数据,因此当我的脚本检查页面区域以及页面元素的订单特定数据时,它还不存在。即,<h3>data-property=GBL_ORDERNUMBERSYMBOL 尚不存在,但在浏览器中,如果您让它再加载十秒钟,DOM 和 HTML 会更改以反映特定的订单详细信息。

捕获这些事后加载的数据的最佳方法是什么?我曾尝试使用 watir-webdriver,但也不确定我需要做什么才能使其正常工作。

【问题讨论】:

  • 我认为你的意思是 AJAX 用于异步加载。
  • 确保您遵守他们的使用政策。这对我来说并不明显,因为他们没有 robots.txt,但这并不意味着您不必阅读他们的条件。

标签: ruby screen-scraping nokogiri watir watir-webdriver


【解决方案1】:

尝试安装Capybara-webkit(确保您已安装 QtWebKit,否则 gem 安装将失败)。这将为您提供无头解决方案。然后试试这个:

require 'capybara-webkit'
require 'capybara/dsl'
require 'nokogiri'
require 'open-uri'

url = 'http://www.hollisterco.com/webapp/wcs/stores/servlet/TrackDetail?storeId=10251&catalogId=10201&langId=-1&URL=TrackDetailView&orderNumber=1316358'
#change the capybara config to DSL and to use webkit
include Capybara::DSL
Capybara.current_driver = :webkit
visit(url)
doc = Nokogiri::HTML.parse(body)

然后像往常一样解析正文。要删除所有错误消息,请尝试以下操作:

Capybara.register_driver :webkit do |app|
  Capybara::Driver::Webkit.new(app, :stdout => nil)
end

【讨论】:

  • 您会将代码放在哪里以删除“错误”消息?当我在 Capybara.current_driver = :webkit 之后添加它时,我在调用 visit(url) ... wrong number of arguments (2 for 0) 时得到以下信息
  • 作为提示,qt 安装可能需要一段时间 - 在我的情况下为 2 小时:github.com/Homebrew/legacy-homebrew/issues/4166
【解决方案2】:

我不知道如何使用 Open-URI,但如果你想使用 Watir-Webdriver,以下工作。

require 'watir-webdriver'
b = Watir::Browser.new
b.goto('http://www.hollisterco.com/webapp/wcs/stores/servlet/TrackDetail?storeId=10251&catalogId=10201&langId=-1&URL=TrackDetailView&orderNumber=1316358')
puts b.h3(:class, 'order-num').when_present.text

请注意,when_present() 是在 h3 标签上执行的。这意味着脚本将等待 h3 出现,然后再尝试获取其文本。如果您知道有些部分需要一些时间来加载,那么添加显式等待通常可以解决问题。

【讨论】:

  • Open::URI 只能在 Ajax 方法触发之前检索原始页面。基于 Watir 的宝石是最佳解决方案。
  • 太棒了-谢谢。效果很好。最后一个问题:有没有办法让它实际上不打开新的浏览器?如果我想抓取多个页面,恐怕这可能需要很长时间......关于如何加速事情的想法?
  • 不打开新浏览器是什么意思?你的意思是你想让一切都在后台运行还是你想使用现有的浏览器?
  • 我想知道是否有运行多个线程的好方法 - 我的问题是打开浏览器窗口,等待它找到数据,然后关闭并打开新浏览器需要时间 - 有吗在后台或同时使用多个线程更快地运行它的好方法?
  • 您可以使用同一个浏览器完成所有工作。您不必关闭并重新打开一个新的。多线程应该是可能的,但你必须小心浏览器共享会话。您的最佳选择实际上取决于您的上下文。我建议打开一个新问题并描述您的场景。
【解决方案3】:

按照@benaneesh 的回答,我必须稍作修改才能让它在我的 ruby​​ 脚本中工作,并且不显示未知的 url 消息...

require 'capybara-webkit'
require 'capybara/dsl'
require 'nokogiri'
require 'open-uri'

include Capybara::DSL
Capybara.current_driver = :webkit

Capybara::Webkit.configure do |config|
  config.block_unknown_urls
  config.allow_url("*mysite.com")
end

#... rest of code

【讨论】:

    猜你喜欢
    • 2020-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    • 2018-12-04
    相关资源
    最近更新 更多