抓取 - 加载动态按钮
Scraping - Loading dynamic buttons
我正在尝试使用 Ruby 和 Nokogiri 对 Waitrose & Partners 的 "Fresh & Chilled" 产品进行网络抓取。
为了加载更多产品,我需要单击 'Load More...',这将动态加载更多产品,而无需更改 URL 或重定向到新页面。
如何 'click' "Load More" 按钮加载更多产品?
我认为这是一个动态网站,因为在单击 "Load More..." 按钮后动态加载项目并且 URL 根本没有改变(因此没有分页可见)
这是我迄今为止尝试过的代码,但我无法加载更多项目。我的猜测是 DOM 正在自行加载,但您实际上不能单击该按钮,因为它代表调用 javascript 方法来加载其余项目。
require "csv"
require "json"
require "nokogiri"
require "open-uri"
require "pry"
def scrape_category(category)
CSV.open("out/waitrose_items_#{category}.csv", "w") do |csv|
headers = [:id, :name, :category, :price_per_unit, :price_per_quantity, :image_url, :available, :url]
csv << headers
url = "https://www.waitrose.com/ecom/shop/browse/groceries/#{category}"
html = open(url)
doc = Nokogiri::HTML(html)
load_more = doc.css(".loadMoreWrapper___UneG1").first
pages = 0
while load_more != nil
puts pages.to_s
load_more.content # Here's where I don't know how to click the button to load more items
products = doc.css(".podHeader___3yaub")
puts "products = " + products.length.to_s
pages = pages + 1
load_more = doc.css(".loadMoreWrapper___UneG1").first
end
(0..products.length-1).each do |i|
puts "url = " + products[i].text
end
load_more = doc.css(".loadMoreWrapper___UneG1")[0]
# here goes the processing of each single item to put in csv file
end
end
def scrape_waitrose
categories = [
"fresh_and_chilled",
]
threads = categories.map do |category|
Thread.new { scrape_category(category) }
end
threads.each(&:join)
end
#binding.pry
Nokogiri 是一种解析方式HTML。它是 Ruby 相当于 Javascript 的 Cheerio 或 Java 的 Jsoup。这实际上不是 Nokogiri 问题。
您感到困惑的是解析 HTML 的方式和收集 HTML 的方法,这些都是通过网络传送的。重要的是要记住许多功能,例如您的按钮点击,都是由 Java 脚本启用的。如今,许多网站(例如 React 网站)完全由 Javascript 构建。
所以当你执行这一行时:
doc = Nokogiri::HTML(html)
这是您必须关注的html变量。您的 html 与我在浏览器中从同一页面查看的 html 不同。
为了进行任何类型的可靠网络抓取,您必须使用将执行Java脚本文件的无头浏览器。在 Ruby 术语中,这曾经意味着使用 Poltergeist 来控制 Phantomjs,Webkit 浏览器的无头版本。当 Puppeteer 和 headless Chrome 到来时,Phantomjs 变得不受支持。
我正在尝试使用 Ruby 和 Nokogiri 对 Waitrose & Partners 的 "Fresh & Chilled" 产品进行网络抓取。
为了加载更多产品,我需要单击 'Load More...',这将动态加载更多产品,而无需更改 URL 或重定向到新页面。
如何 'click' "Load More" 按钮加载更多产品?
我认为这是一个动态网站,因为在单击 "Load More..." 按钮后动态加载项目并且 URL 根本没有改变(因此没有分页可见)
这是我迄今为止尝试过的代码,但我无法加载更多项目。我的猜测是 DOM 正在自行加载,但您实际上不能单击该按钮,因为它代表调用 javascript 方法来加载其余项目。
require "csv"
require "json"
require "nokogiri"
require "open-uri"
require "pry"
def scrape_category(category)
CSV.open("out/waitrose_items_#{category}.csv", "w") do |csv|
headers = [:id, :name, :category, :price_per_unit, :price_per_quantity, :image_url, :available, :url]
csv << headers
url = "https://www.waitrose.com/ecom/shop/browse/groceries/#{category}"
html = open(url)
doc = Nokogiri::HTML(html)
load_more = doc.css(".loadMoreWrapper___UneG1").first
pages = 0
while load_more != nil
puts pages.to_s
load_more.content # Here's where I don't know how to click the button to load more items
products = doc.css(".podHeader___3yaub")
puts "products = " + products.length.to_s
pages = pages + 1
load_more = doc.css(".loadMoreWrapper___UneG1").first
end
(0..products.length-1).each do |i|
puts "url = " + products[i].text
end
load_more = doc.css(".loadMoreWrapper___UneG1")[0]
# here goes the processing of each single item to put in csv file
end
end
def scrape_waitrose
categories = [
"fresh_and_chilled",
]
threads = categories.map do |category|
Thread.new { scrape_category(category) }
end
threads.each(&:join)
end
#binding.pry
Nokogiri 是一种解析方式HTML。它是 Ruby 相当于 Javascript 的 Cheerio 或 Java 的 Jsoup。这实际上不是 Nokogiri 问题。
您感到困惑的是解析 HTML 的方式和收集 HTML 的方法,这些都是通过网络传送的。重要的是要记住许多功能,例如您的按钮点击,都是由 Java 脚本启用的。如今,许多网站(例如 React 网站)完全由 Javascript 构建。
所以当你执行这一行时:
doc = Nokogiri::HTML(html)
这是您必须关注的html变量。您的 html 与我在浏览器中从同一页面查看的 html 不同。
为了进行任何类型的可靠网络抓取,您必须使用将执行Java脚本文件的无头浏览器。在 Ruby 术语中,这曾经意味着使用 Poltergeist 来控制 Phantomjs,Webkit 浏览器的无头版本。当 Puppeteer 和 headless Chrome 到来时,Phantomjs 变得不受支持。