11.1 Splash 渲染引擎
Splash是Scrapy官方推荐的JavaScript渲染引擎,它是使用Webkit开发的轻量级无界面浏览器,提供基于HTTP接口的JavaScript渲染服务,支持以下功能:
为用户返回经过渲染的HTML页面或页面截图。
并发渲染多个页面。
关闭图片加载,加速渲染。
在页面中执行用户自定义的JavaScript代码。
执行用户自定义的渲染脚本(lua),功能类似于PhantomJS。
首先安装Splash,在linux下使用docker安装十分方便:
$ sudo apt-get install docker $ sudo docker pull scrapinghub/splash
安装完成后,在本机的8050和8051端口开启Splash服务:
$ sudo docker run -p 8050:8050 -p 8051:8051 scrapinghub/splash [-] Log opened. [-] Splash version: 2.1 [-] Qt 5.5.1, PyQt 5.5.1, WebKit 538.1, sip 4.17, Twisted 16.1.1, Lua 5.2 [-] Python 3.5 (default, Oct 14 2015, 20:28:29) [GCC 4.8.4] [-] Open files limit: 524288 [-] Open files limit increased from 524288 to 1048576 [-] Xvfb is started: ['Xvfb', ':1', '-screen', '0', '1024x768x24'] [-] proxy profiles support is enabled, proxy profiles path: /etc/splash/proxy-profiles [-] verbosity=1 [-] slots=50 [-] argument_cache_max_entries=500 [-] Web UI: enabled, Lua: enabled (sandbox: enabled) [-] Site starting on 8050 [-] Starting factory
Splash功能丰富,包含多个服务端点,由于篇幅有限,这里只介绍其中两个最常用的端点:
render.html
提供JavaScript页面渲染服务。
execute
执行用户自定义的渲染脚本(lua),利用该端点可在页面中执行JavaScript代码。
Splash文档地址:http://splash.readthedocs.io/en/latest/api.html。
11.1.1 render.html端点
JavaScript页面渲染服务是Splash中最基础的服务,请看表11-1中列出的文档。
表11-1
render.html端点支持的参数如表11-2所示。
表11-2
这里仅列出部分常用参数,详细内容参见官方文档。
下面是使用requests库调用render.html端点服务对页面http://quotes.toscrape.com/js/进行渲染的示例代码。
>>> import requests >>> from scrapy.selector import Selector >>> splash_url = 'http://localhost:8050/render.html' >>> args = {'url': 'http://quotes.toscrape.com/js', 'timeout': 5, 'image': 0} >>> response = requests.get(splash_url, params=args) >>> sel = Selector(response) >>> sel.css('div.quote span.text::text').extract() #提取所有名人名言 ['“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”', '“It is our choices, Harry, that show what we truly are, far more than our abilities.”', '“There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”', '“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”', "“Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”", '“Try not to become a man of success. Rather become a man of value.”', '“It is better to be hated for what you are than to be loved for what you are not.”', "“I have not failed. I've just found 10,000 ways that won't work.”", "“A woman is like a tea bag; you never know how strong it is until it's in hot water.”", '“A day without sunshine is like, you know, night.”']
在上述代码中,依据文档中的描述设置参数url、timeout、images,然后发送HTTP请求到服务接口地址。从运行结果看出,页面渲染成功,我们爬取到了页面中的10条名人名言。
11.1.2 execute端点
在爬取某些页面时,我们想在页面中执行一些用户自定义的JavaScript代码,例如,用JavaScript模拟点击页面中的按钮,或调用页面中的JavaScript函数与服务器交互,利用Splash的execute端点提供的服务可以实现这样的功能。请看表11-3中的文档。
表11-3
execute端点支持的参数如表11-4所示。
表11-4
我们可以将execute端点的服务看作一个可用lua语言编程的浏览器,功能类似于PhantomJS。使用时需传递一个用户自定义的lua脚本给Splash,该lua脚本中包含用户想要模拟的浏览器行为,例如:
打开某url地址的页面
等待页面加载及渲染
执行JavaScript代码
获取HTTP响应头部
获取Cookie
下面是使用requests库调用execute端点服务的示例代码。
>>> import requests >>> import json >>> lua_script = ''' ... function main(splash) ... splash:go("http://example.com") --打开页面 ... splash:wait(0.5) --等待加载 ... local title = splash:evaljs("document.title") --执行js代码获取结果 ... return {title=title} --返回json 形式的结果 ... end ... ''' >>> splash_url = 'http://localhost:8050/execute' >>> headers = {'content-type': 'application/json'} >>> data = json.dumps({'lua_source': lua_script}) >>> response = requests.post(splash_url, headers=headers, data=data) >>> response.content b'{"title": "Example Domain"}' >>> response.json() {'title': 'Example Domain'}
用户自定义的lua脚本中必须包含一个main函数作为程序入口,main函数被调用时会传入一个splash对象(lua中的对象),用户可以调用该对象上的方法操纵Splash。例如,在上面的例子中,先调用go方法打开某页面,再调用wait方法等待页面渲染,然后调用evaljs方法执行一个JavaScript表达式,并将结果转化为相应的lua对象,最终Splash根据main函数的返回值构造HTTP响应返回给用户,main函数的返回值可以是字符串,也可以是lua中的表(类似Python字典),表会被编码成json串。
接下来,看一下splash对象常用的属性和方法。
splash.args属性
用户传入参数的表,通过该属性可以访问用户传入的参数,如splash.args.url、splash.args.wait。
splash.js_enabled属性
用于开启/禁止JavaScript渲染,默认为true。
splash.images_enabled属性
用于开启/禁止图片加载,默认为true。
splash:go方法
splash:go{url, baseurl=nil, headers=nil, http_method="GET", body=nil, formdata=nil}
类似于在浏览器中打开某url地址的页面,页面所需资源会被加载,并进行JavaScript渲染,可以通过参数指定HTTP请求头部、请求方法、表单数据等。
splash:wait方法
splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}等待页面渲染,time参数为等待的秒数。
splash:evaljs方法
splash:evaljs(snippet)
在当前页面下,执行一段JavaScript代码,并返回最后一句表达式的值。
splash:runjs方法
splash:runjs(snippet)
在当前页面下,执行一段JavaScript代码,与evaljs方法相比,该函数只执行JavaScript代码,不返回值。
splash:url方法
splash:url()
获取当前页面的url。
splash:html方法
splash:html()
获取当前页面的HTML文本。
splash:get_cookies方法
splash:get_cookies()
获取全部Cookie信息.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论