最近在用 python 的 scrapy 写亚马逊详情页爬虫时候,遇到一个问题,就是抓取回来的数据,没有价格、FBA物流等数据,由于接触scrapy爬虫的时间并不长,特此记录一下。
一、问题描述
用scrapy 爬取亚马逊详情页信息数据,该链接是有价格数据,但是抓取回来就是没有价格。刚开始以为是遇到反爬了,所以更换了UA请求头,添加了cookie,甚至更换了代理IP,问题还是没有解决。
先给出结论:抓取不到是因为邮编显示中国,因此需要通过修改session的方式改变邮编地址。不想看分析过程的可以直接跳到第四点。
二、分析过程
重点是,发现固定有几个listing的价格是一直抓取不成功,如果是遇到反爬,也不可能只有这几个listing抓不到,所以判断一定是这些listing 有不一样的地方。
于是分别把抓取成功和不成功的listing页面数据全部复制下来。
1.正常的页面解析及爬取的页面文本
2.抓取失败的页面
也就是说,抓取不到价格的listing,返回的页面解析,根本就没有价格这个信息,那首先可以排除是xpath解析出错,或是页面标签发生变化,导致解析不到。
那么问题就是,scrapy的request请求返回的页面,一开始就是没有价格!
后来通过对比发现,因为亚马逊邮编定位是在中国,这些listing由于不能发货到中国,所以在国内访问该链接,是不显示价格,这就解释了为什么固定某些listing是抓取不到价格信息。
三、解决思路
“因此需要解决的问题就是把邮编改成当地邮编
那么邮编的数据是怎么传给亚马逊服务器?大致会有3种方式:
1.网址参数
2.cookie参数
3.session参数
通过在页面修改网址,发现网址没有发生变化,首先排除第一种网址链接参数。
对比了cookie,也没有发生变化,排除第二种邮编信息在cookie中,因此邮编信息是在session中,也就是在亚马逊服务器中。
cookie、session和token的关系和原理,可以在网上搜,有很多大佬的文章,我就不重复累赘了。
四、代码实现
1、setting.py中,填写cookie信息,注意要写全,还有cookie_enabled要设置为False。
COOKIES_ENABLED = False
cookie_us = [
"session-id=143-9242614-7545859; session-id-time=2082787201l; i18n-prefs=USD; lc-main=en_US; ubid-main=133-8198735-5159518; session-token=eM2XrktDKdMHl8dFWqMCM9fxt2wAd9XiUaIt9XV5Idn5txx3CEaVpPLzUSX0jzBOMUrluDMZG2fYQhS2MnJIuJen/S3GqaaaZwa0Ocau1cnm6p574aXcazmPeNgRZfBOhTsLWFr3dKKr93I5wvmFOnljmE1Cew+C69UVKTwWssgtZICJ/mF8OyCb1heORnFL; csm-hit=tb:GK6JXZJS0G5M8MM0HAGP+s-V0YX945PDE3RB3C9HB74|1637462213864&t:1637462213864&adb:adblk_no",
]
2、middlewares.py重写中间件
class AmazonSpiderDownloaderMiddleware:
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
def process_request(self, request, spider):
settings = get_project_settings()
user_agent = random.choice(settings['USER_AGENT_LIST'])
request.headers['User-Agent'] = user_agent
spider.logger.debug("[User-Agent]: {}".format(user_agent))
# 如果是美国站地址,则更改美国cookie信息
if '.com/' in request.url:
request.headers['cookie'] = random.choice(cookie_us)
return None
五、总结
根据代码测试,确实是因为cookie信息导致,亚马逊会认为访问者邮编是中国地区,导致部分信息显示不全。更换cookie后,问题就修复了。需要优化的是,要建立检测模块,当cookie过期后,通过selenium自动获取新cookie。
也许会有人有疑问,既然要用selenium获取并更新cookie,为什么不直接用selenium访问页面,然后在页面上更改?其实这做法是可以的,但是selenium采集速度比较慢,爬取数量大的时候是不适用的,我习惯上能不用selenium就尽量不用。