使用splash爬去JavaScript动态请求的内容

来源:互联网 发布:驾驶员网络培训 编辑:程序博客网 时间:2024/06/08 04:21

splash简介

Splash是一个Javascript渲染服务。它是一个实现了HTTP API的轻量级浏览器,Splash是用Python实现的,同时使用Twisted和QT。Twisted(QT)用来让服务具有异步处理能力,以发挥webkit的并发能力.

splash安装

1.利用pip安装scrapy-splash库

pip install scrapy-splash

2.下载运行docker与下载splash镜像

(1)scrapy-splash使用的是Splash HTTP API,一般采用docker运行splash,所以需要安装docker,接下来安装docker。
由于国外镜像速度真的是慢的不行,这里使用阿里云的镜像容器加速器,注册阿里云后选择镜像容器服务下的Docker Hub 镜像站点,具体内容如下图
展示图片

(2)配置好了以后。接下来启动docker:
sudo service docker start

测试是否启动成功 sudo docker run hello-world

(3)接下来就是拉取splash镜像文件

sudo docker pull scrapinghub/splash

连接的时候这时候可能timeout,重新执行命令就好了

(4)接下来用docker运行splash,要使用root权限,不然就会显示未启动docker,设置端口:

sudo docker run -p 8050:8050 scrapinghub/splash

使用splash编写爬虫

1.在scrapy项目中配置splash

相关配置在setting.py中

#添加splash服务器地址:SPLASH_URL = 'http://localhost:8050'#在你的下载器中间件:download_middleware 里面启用如下的中间文件,注意启用的顺序DOWNLOADER_MIDDLEWARES = {'scrapy_splash.SplashCookiesMiddleware': 723,'scrapy_splash.SplashMiddleware': 725,'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,}#在settings.py启用SplashDeduplicateArgsMiddleware中间件SPIDER_MIDDLEWARES = {'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,}#设置一个去重的类DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'#启用这个scrapy-splash的缓存系统HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

2.简单实例

首先看看pycharm如何运行scrapy
转载pycharm下打开、执行并调试scrapy爬虫程序
接下来是对比scrapy和splash,以bilibili的一个动态加载的数字为例

# -*- coding = utf-8 -*-#scrapyimport scrapyimport loggingclass scrapyTest(scrapy.Spider):    name = 'ordinary' #这个名字就是上面连接中那个启动应用的名字    allowed_domain = ["bilibili.com"]    start_urls = [        "https://www.bilibili.com/"    ]    def parse(self, response):        logging.info('====================================================')        content = response.xpath("//div[@class='num-wrap']").extract_first()        logging.info(content)        logging.info('====================================================')

这是结果,num里的内容没有获取到,接下来用splash

关于splash的参数的详细解释会在文章末尾给出^_^

这里写图片描述

# -*- coding = utf-8 -*-#splashimport scrapyfrom scrapy_splash import SplashRequestimport loggingclass splash(scrapy.Spider):    name = "test"    allowed_domains = ["bilibili.com"]    start_urls = [        "https://www.bilibili.com/"    ]    def start_requests(self):        splash_args = {            'wait': '5',        }        for url in self.start_urls:            yield SplashRequest(url, self.parse_result, args=splash_args, endpoint='render.html')    def parse_result(self, response):        logging.info('====================================================')        content = response.xpath("//div[@class='num-wrap']").extract_first()        logging.info(content)        logging.info('====================================================')

这里写图片描述

当当当当,这里得到了数字了

3.splash参数详解

api里有两种请求方式
方式一:使用scrapy_splash.SplashRequest

    yield SplashRequest(url, self.parse_result,          args={              # optional; parameters passed to Splash HTTP API              # 'wait'             # 'url' is prefilled from request url              # 'http_method' is set to 'POST' for POST requests              # 'body' is set to request body for POST requests          },          endpoint='render.json', # optional; default is render.html          splash_url='<url>',     # optional; overrides SPLASH_URL          slot_policy=scrapy_splash.SlotPolicy.PER_DOMAIN,  # optional      )  

方式二:在普通的scrapy请求中传递splash请求meta关键字

    yield scrapy.Request(url, self.parse_result, meta={          'splash': {              'args': {                  # set rendering arguments here                  '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.json',  # optional; default is render.json              'splash_url': '<url>',      # optional; overrides SPLASH_URL              'slot_policy': scrapy_splash.SlotPolicy.PER_DOMAIN,              'splash_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          }      })  

Splash API说明,使用SplashRequest是一个非常便利的工具来填充>request.meta[‘splash’]里的数据

meta[‘splash’][‘args’] 包含了发往Splash的参数。
meta[‘splash’][‘endpoint’] 指定了Splash所使用的endpoint,> > 默认是render.html
meta[‘splash’][‘splash_url’] 覆盖了settings.py文件中配置的> > Splash URL
meta[‘splash’][‘splash_headers’] 运行你增加或修改发往> > > Splash服务器的HTTP头部信息,注意这个不是修改发往远程web站点的HTTP头部
meta[‘splash’][‘dont_send_headers’] 如果你不想传递headers给Splash,将它设置成True
meta[‘splash’][‘slot_policy’] 让你自定义Splash请求的同步设置
meta[‘splash’][‘dont_process_response’] 当你设置成True后,SplashMiddleware不会修改默认的scrapy.Response请求。默认是会返回SplashResponse子类响应比如SplashTextResponse
meta[‘splash’][‘magic_response’] 默认为True,Splash会自动设置Response的一些属性,比如response.headers,response.body等

如果你想通过Splash来提交Form请求,可以使用scrapy_splash.SplashFormRequest,它跟SplashRequest使用是一样的。

对于不同的Splash请求,scrapy-splash返回不同的Response子类
SplashResponse 二进制响应,比如对/render.png的响应
SplashTextResponse 文本响应,比如对/render.html的响应
SplashJsonResponse JSON响应,比如对/render.json或使用Lua脚本>的/execute的响应

如果你只想使用标准的Response对象,就设置meta[‘splash’][‘dont_process_response’]=True

所有这些Response会把response.url设置成原始请求URL(也就是你要渲染的页面URL),而不是Splash endpoint的URL地址。实际地址通过response.real_url得到

文章参考了以下文章:
http://blog.csdn.net/sdulsj/article/details/52984913
http://blog.csdn.net/u012052268/article/details/72063917
http://www.cnblogs.com/zhonghuasong/p/5976003.html

原创粉丝点击