爬虫之Splash基础篇

一 点睛

Splash是一个JavaScript渲染服务,是一个带有HTTP API的轻量级浏览器,同时它对接了Python中的Twisted和QT库。利用它,我们同样可以实现动态渲染页面的抓取。

二 功能介绍

利用Splash,我们可以实现如下功能:

  • 异步方式处理多个网页渲染过程;

  • 获取渲染后的页面的源代码或截图;

  • 通过关闭图片渲染或者使用Adblock规则来加快页面渲染速度;

  • 可执行特定的JavaScript脚本;

  • 可通过Lua脚本来控制页面渲染过程;

  • 获取渲染的详细过程并通过HAR(HTTP Archive)格式呈现。

三 Splash服务的安装

1 通过Docker安装Splash的服务

[[email protected] ~]# docker run -p 8050:8050 scrapinghub/splash

爬虫之Splash基础篇

2 测试安装是否成功

访问http://localhost:8050/

爬虫之Splash基础篇

四 scrapy-splash库的安装

(venv) E:\WebSpider>pip install scrapy-splash

五 实例引入

1 通过Splash提供的Web页面来测试其渲染过程。例如,我们在本机8050端口上运行了Splash服务,打开http://localhost:8050/即可看到其Web页面。

爬虫之Splash基础篇

2 右侧呈现的是一个渲染示例。可以看到,上方有一个输入框,默认是http://google.com,这里换成百度测试一下,将内容更改为https://www.baidu.com,然后点击Render me按钮开始渲染,结果如下:

爬虫之Splash基础篇

3 可以看到,网页的返回结果呈现了渲染截图、HAR加载统计数据、网页的源代码。

通过HAR的结果可以看到,Splash执行了整个网页的渲染过程,包括CSS、JavaScript的加载等过程,呈现的页面和我们在浏览器中得到的结果完全一致。

4 脚本代码

function main(splash, args)
  assert(splash:go(args.url))
  assert(splash:wait(0.5))
  return {
    html = splash:html(),
    png = splash:png(),
    har = splash:har(),
  }

5 脚本分析

这个脚本实际上是用Lua语言写的脚本。即使不懂这个语言的语法,但从脚本的表面意思,我们也可以大致了解到它首先调用go()方法去加载页面,然后调用wait()方法等待了一定时间,最后返回了页面的源码、截图和HAR信息。

到这里,我们大体了解了Splash是通过Lua脚本来控制了页面的加载过程的,加载过程完全模拟浏览器,最后可返回各种格式的结果,如网页源码和截图等。

六 Splash Lua脚本

1 点睛

Splash可以通过Lua脚本执行一系列渲染操作,这样我们就可以用Splash来模拟类似Chrome、PhantomJS的操作了。

2 入口及返回值

2.1 代码

function main(splash, args)
  splash:go("http://www.baidu.com")
  splash:wait(0.5)
  local title = splash:evaljs("document.title")
  return {title=title}
end

2.2 结果

爬虫之Splash基础篇

2.3 说明

注意,我们在这里定义的方法名称叫作main()。这个名称必须是固定的,Splash会默认调用这个方法。

该方法的返回值既可以是字典形式,也可以是字符串形式,最后都会转化为Splash HTTP Response。

2.3.1 返回字典代码

function main(splash)
    return {hello="world!"}
end

2.3.2 返回字符串

function main(splash)
    return 'hello'
end

2.3.3 结果

爬虫之Splash基础篇

3 异步处理

3.1 点睛

Splash支持异步处理,但是这里并没有显式指明回调方法,其回调的跳转是在Splash内部完成的。

3.2 代码

function main(splash, args)
  local example_urls = {"www.baidu.com", "www.taobao.com", "www.zhihu.com"}
  local urls = args.urls or example_urls
  local results = {}
  for index, url in ipairs(urls) do
    local ok, reason = splash:go("http://" .. url)
    if ok then
      splash:wait(2)
      results[url] = splash:png()
    end
  end
  return results
end

3.3 结果

爬虫之Splash基础篇

3.4 说明

在脚本内调用的wait()方法类似于Python中的sleep(),其参数为等待的秒数。当Splash执行到此方法时,它会转而去处理其他任务,然后在指定的时间过后再回来继续处理。

这里值得注意的是,Lua脚本中的字符串拼接和Python不同,它使用的是..操作符,而不是+。如果有必要,可以简单了解一下Lua脚本的语法,详见http://www.runoob.com/lua/lua-basic-syntax.html

另外,这里做了加载时的异常检测。go()方法会返回加载页面的结果状态,如果页面出现4xx或5xx状态码,ok变量就为空,就不会返回加载后的图片。