Scrapy爬取亚马逊商品页结果不一致 时而返回None如何解决
问题根因
- 亚马逊具备严格的反爬虫检测机制,你看到的200状态码不代表返回了真实商品页面:触发反爬时亚马逊会返回人机验证页、区域限制页或者空白跳转页,这类页面不存在你要匹配的
productTitle节点,所以返回None。少量成功的请求是暂时未触发反爬规则的偶发情况。
解决方案
1. 配置真实浏览器请求头
Scrapy默认携带的Scrapy/版本号格式User-Agent会被直接识别为爬虫,你需要替换为真实浏览器的请求头,条件允许的话可以搭建User-Agent池随机切换:
# 构造请求时传入headers参数,示例UA可替换为你自己浏览器的真实UA headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36", "Accept-Language": "en-US,en;q=0.9", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" } yield Request( url="https://www.amazon.com/%C2%A1Avancemos-Student-Level-2013-Spanish/dp/0547871929", callback=self.parse, dont_filter=True, headers=headers )
2. 降低请求频率规避风控
Scrapy默认的高并发、短间隔请求特征明显,在settings.py中调整以下参数降低被识别概率:
DOWNLOAD_DELAY = 3 # 单请求间隔至少3秒 CONCURRENT_REQUESTS_PER_DOMAIN = 1 # 亚马逊域名下同一时间仅发送1个请求 RANDOMIZE_DOWNLOAD_DELAY = True # 随机化请求间隔,消除请求规律
3. 增加页面校验逻辑
拿到响应后先判断是否为真实商品页,异常情况可以自动重试或者存下页面调试:
def parse(self, response): # 检测是否触发人机验证 if "robot check" in response.text.lower() or "enter the characters you see" in response.text.lower(): # 触发验证时自动重试,重试次数可自行限制 yield Request( url=response.url, callback=self.parse, dont_filter=True, headers=headers, meta={"retry_times": response.meta.get("retry_times", 0) + 1} ) return title = response.xpath('//span[@id="productTitle"]/text()').get() # 未匹配到标题时保存页面内容方便调试 if not title: with open("debug_page.html", "w", encoding="utf-8") as f: f.write(response.text) yield { "title": title.strip() if title else None }
4. 搭配代理IP池
如果调整后成功率仍较低,说明你的本地IP已经被亚马逊临时限制,需要接入高匿代理IP池,每次请求随机切换IP,避免单IP请求过多被封禁。
内容的提问来源于stack exchange,提问作者Avn
相关产品推荐
相关产品推荐

