我正在尝试在亚马逊畅销书 100 中抓取特定类别的产品。例如-
https://www.amazon.com/Best-Sellers-Home-Kitchen/zgbs/home-garden/ref=zg_bs_nav_0
这100个产品分为两页,每页50个产品。
此前,该页面是静态的,所有 50 种产品都会显示在该页面上。然而,现在页面是动态的,我需要向下滚动才能看到页面上的所有 50 个产品。
我之前使用 scrapy 来抓取页面。如果您能帮我解决这个问题,我将不胜感激。谢谢!
在下面添加我的代码-
import scrapy
from scrapy_splash import SplashRequest
class BsrNewSpider(scrapy.Spider):
name = 'bsr_new'
allowed_domains = ['www.amazon.in']
#start_urls = ['https://www.amazon.in/gp/bestsellers/kitchen/ref=zg_bs_nav_0']
script = '''
function main(splash, args)
splash.private_mode_enabled = false
url = args.url
assert(splash:go(url))
assert(splash:wait(0.5))
return splash:html()
end
'''
def start_requests(self):
url = 'https://www.amazon.in/gp/bestsellers/kitchen/ref=zg_bs_nav_0'
yield SplashRequest(url, callback = self.parse, endpoint = "execute", args = {
'lua_source': self.script
})
def parse(self, response):
for rev in response.xpath("//div[@id='gridItemRoot']"):
yield {
'Segment': "Home", #Enter name of the segment here
#'Sub-segment':segment,
'ASIN' : rev.xpath(".//div/div[@class='zg-grid-general-faceout']/div/a[@class='a-link-normal']/@href").re('\S*/dp/(\S+)_\S+')[0][:10],
'Rank' : rev.xpath(".//span[@class='zg-bdg-text']/text()").get(),
'Name' : rev.xpath("normalize-space(.//a[@class='a-link-normal']/span/div/text())").get(),
'No. of Ratings' : rev.xpath(".//span[contains(@class,'a-size-small')]/text()").get(),
'Rating' : rev.xpath(".//span[@class='a-icon-alt']/text()").get(),
'Price' : rev.xpath(".//span[@class='a-size-base a-color-price']//text()").get()
}
next_page = response.xpath("//a[text()='Next page']/@href").get()
if next_page:
url = response.urljoin(next_page)
yield SplashRequest(url, callback = self.parse, endpoint = "execute", args = {
'lua_source': self.script
})
问候 斯里詹
这是一种不需要 Splash 的替代方法。
所有 50 个产品的 ASIN 都隐藏在首页上。您可以提取这些 ASIN 并构建所有这 50 个产品 URL。
import scrapy
import json
class AmazonSpider(scrapy.Spider):
custom_settings ={
'DEFAULT_REQUEST_HEADERS':''# Important
}
name = 'amazon'
start_urls = ['https://www.amazon.com/Best-Sellers-Home-Kitchen/zgbs/home-garden/ref=zg_bs_pg_1?_encoding=UTF8&pg=1']
def parse(self, response):
raw_data = response.css('[data-client-recs-list]::attr(data-client-recs-list)').get()
data = json.loads(raw_data)
for item in data:
url = 'https://www.amazon.com/dp/{}'.format(item['id'])
yield scrapy.Request(url, callback=self.parse_item)
def parse_item(self, response,):
...
由于内容的异步加载方式,抓取动态内容(尤其是从亚马逊等网站)可能非常具有挑战性。就您而言,由于亚马逊畅销书页面已变为动态并且需要滚动才能加载所有产品,因此您当前的 Scrapy 设置可能不够。
您的代码使用 Splash,这是处理 JavaScript 渲染内容的不错选择。但是,要处理滚动部分,您可能需要修改 SplashRequest 中的 Lua 脚本。您需要在 Lua 脚本中添加一个循环,该循环向下滚动页面,直到加载所有产品。这可以通过模拟滚动事件或等待某些元素出现来指示页面已完成加载新产品来完成。
这是一个修改后的 Lua 脚本片段,您可能会觉得有用:
function main(splash, args)
splash.private_mode_enabled = false
assert(splash:go(args.url))
assert(splash:wait(1))
-- Scroll down until all products are loaded
local get_scroll_height = "return document.body.scrollHeight"
local scroll_height = splash:evaljs(get_scroll_height)
while true do
assert(splash:runjs("window.scrollTo(0, document.body.scrollHeight);"))
assert(splash:wait(1))
local new_scroll_height = splash:evaljs(get_scroll_height)
if new_scroll_height == scroll_height then
break
end
scroll_height = new_scroll_height
end
return splash:html()
end
在此脚本中,页面滚动,直到文档的 'scrollHeight' 停止变化,表示没有加载新产品。
关于您的 Scrapy 代码,请确保 XPath 正确定位更新的 Amazon 页面结构中的元素。动态页面经常改变其结构,这可能需要定期更新您的抓取逻辑。
作为替代或补充工具,您可以考虑使用 Crawlbase。它可以处理 JavaScript 渲染的页面,并可能简化抓取此类动态内容的过程。 Crawlbase 提供自动处理代理、验证码和基于规则的爬行等功能,这对于像您这样的复杂抓取任务非常有帮助。但是,请记住在抓取亚马逊网站时遵守亚马逊的服务条款和法律法规。