scrapy对接scrapy-splash
发布时间丨2021-12-09 19:14:08作者丨zhaomeng浏览丨8
最近工作中需要采集一些文献作为项目的内容,依旧是使用scrapy框架作为爬虫项目的基础,搭建分布式爬虫系统,提高效率。但是在分析到详情信息的时候发现,作者的基本信息无法获取到,看了一下是基于第三方的js渲染出来的(可以确认的是页面对作者信息做了保护,直接点击页面的作者信息的链接,会转到一个页面,意思就是不支持javascript)到这里我一开始是使用的selenium作为渲染的中间件,但是使用的效果并不理想,后来就使用了官方的scrapy-splash这个插件,这个需要安装,我是使用docker进行安装的。之后就是对他的使用有几种方式,下面一一解答。这个工具我一开始使用的常规的代理中间件的赋值方式,后来一直运行也正常,但实际时使用的本机IP,直到前天这个网站显示封掉了,爬虫报错了,what?什么鬼!,开始在网上找资料,终于找到了scrapy-splash的代理赋值不同于常规的方式。以为就此解决了,开始运行依旧不行。满脑子what????,明明代理ip已经添加了啊!输出参数里面也有啊!查资料,找到一篇知乎的文章发现他有讲到splash的代理源码,觉只是个大神,应该没错了,前面都没有问题,唯一不同就是中间件的优先级不同!问题找到啦!网络资源是比较多的但是也不是每篇都是对的,踩坑经过。特此来记录一下,以防后面时间久了忘了,毕竟不是谁都能背的上自己写的代码的!
第一步:scrapy-splash的docker安装如下:
docker pull scrapinghub/splash
docker run -d -p 8050:8050 --name splash scrapinghub/splash
本机浏览器运行结果如下:
第二步:scrapy-splash在scrapy中的三种使用方式:
首先安装:pip install scrapy-splash
配置settings.py,这里的代理中间件的数字是整个项目代理成功的关键!(这里网上还有博主说要在下载中间件的最后面设置代理中间件数字825,这TM天坑啊,就这个问题加班好一会才爬出来!)
DOWNLOADER_MIDDLEWARES = {
'pubs.middlewares.ProxyMiddleware': 724, # 这个是重点数字小于725才生效
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
项目依旧是按照分部署爬虫的配置进行的,上面的添加到配置文件settings.py就行,其他不变,还有就是spider.py文件的发起请求代码做一些修改,有三种方式:
- 常规的分布式爬虫的入口请求
# return scrapy.Request(url=data.get("url"), # headers=headers, # # dont_filter=True, # callback=self.parse, # cb_kwargs=cb_kwargs # )
- 直接使用官方提供的:SplashRequest(url,callback=self.parse,args={'wait':'0.5'})方法
# return SplashRequest(url=data.get('url'), callback=self.parse, args={'wait': '0.5'}, cb_kwargs=cb_kwargs)
- 使用原生的scrapy.Request()运行splash配置
return scrapy.Request(url=data.get("url"), callback=self.parse, meta={ 'splash': { 'args': { # 在此处设置端点API的参数 'html': 1, 'png': 1, # 'url' is prefilled from request url # 'http_method' is set to 'POST' for POST requests # 'body' is set to request body for POST requests }, # optional parameters 'endpoint': 'render.html', # optional; default is render.json 'splash_url': 'http://*******:8050', # optional; overrides SPLASH_URL 'slot_policy': scrapy_splash.SlotPolicy.PER_DOMAIN, 'splash_headers': headers, # optional; a dict with headers sent to Splash 'dont_process_response': True, # optional, default is False 'dont_send_headers': True, # optional, default is False 'magic_response': False, # optional, default is True } }, cb_kwargs=cb_kwargs)
我这边使用的是第三种的方式,配置splash。
第三步;编写及配置爬虫代理中间件(这里的代理ip池后面有时间也会专门写两篇文章记录一下,与各位分享)代码如下:
def process_request(self, request, spider):
# Called for each request that goes through the downloader
# middleware.
if not request.meta.get('proxy'):
IP = requests.get(url=settings.get('PROXY_URL'))
if IP.status_code == 200:
IP = IP.json()
if spider.name == "detailinfo": # 需要使用splash渲染的爬虫名称
if request.meta.get('_splash_processed') is None:
request.meta['splash']['args']['proxy'] = "http://" + IP.get("ip") # scrapy-splash配置ip
print(request.meta['splash'])
else: # 其余爬虫使用常规的代理配置
request.meta['proxy'] = "http://" + IP.get("ip")
spider.logger.info("使用代理:" + "http://" + IP.get("ip"))
elif IP.status_code == 500:
spider.logger.info("代理服务器出错!")
else:
pass
else:
logging.info("代理存在")
代理信息打印结果如下图:
到这里基本我遇到的代理不生效的问题就解决了!关键就是中间件的优先级问题!详细原因可以参考知乎这篇scrapy-splash的代理不生效?,本片文章没有详细介绍爬虫项目,而是着重记录了scrapy对接scrapy-splash的一系列问题!
文章原创,创作不易,转载请指明出处!