爬虫系列(15)Splash 的使用。

1. Splash介绍

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

2. 安装

2.1 安装docker

这个安装很简单,自行搜索即可,推荐

【Docker教程 | 菜鸟教程】

2.2 拉取镜像

docker pull scrapinghub/splash

2.3 用docker运行scrapinghub/splash

docker run -p 8050:8050 scrapinghub/splash

2.4 查看效果

> 我们在8050端口上运行了Splash服务,打开http://192.168.99.100:8050/即可看到其Web页面

3 Splash对象属性

> 上图中main()方法的第一个参数是splash,这个对象非常重要,它类似于Selenium中的WebDriver对象

3.1 images_enabled

> 设置图片是否加载,默认情况下是加载的。禁用该属性后,可以节省网络流量并提高网页加载速度

> 注意的是,禁用图片加载可能会影响JavaScript渲染。因为禁用图片之后,它的外层DOM节点的高度会受影响,进而影响DOM节点的位置

> 因此,如果JavaScript对图片节点有操作的话,其执行就会受到影响

function main(splash, args)
  splash.images_enabled = false
  splash:go('https://www.baidu.com')
  return {html=splash:html()}
end

3.2 plugins_enabled

> 可以控制浏览器插件(如Flash插件)是否开启

> 默认情况下,此属性是false,表示不开启

splash.plugins_enabled = true/false

3.3 scroll_position

> 控制页面上下或左右滚动

splash.scroll_position = {x=100, y=200}

4. Splash对象的方法

4.1 go()

> 该方法用来请求某个链接,而且它可以模拟GET和POST请求,同时支持传入请求头、表单等数据

ok, reason = splash:go{url, baseurl=nil, headers=nil, http_method="GET", body=nil, formdata=nil}

> 返回结果是结果ok和原因reason

> 如果ok为空,代表网页加载出现了错误,此时reason变量中包含了错误的原因

参数

含义

url

请求的URL

baseurl

可选参数,默认为空,表示资源加载相对路径

headers

可选参数,默认为空,表示请求头

http_method

可选参数,默认为GET,同时支持POST

body

可选参数,默认为空,发POST请求时的表单数据,使用的Content-type为application/json

formdata

可选参数,默认为空,POST的时候的表单数据,使用的Content-type为application/x-www-form-urlencoded

splash:go{"http://www.sxt.cn", http_method="POST", body="name=17703181473"}

4.2 wait()

> 控制页面的等待时间

splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}

参数

含义

time

等待的秒数

cancel_on_redirect

可选参数,默认为false,表示如果发生了重定向就停止等待,并返回重定向结果

cancel_on_error

可选参数,默认为false,表示如果发生了加载错误,就停止等待

function main(splash)
    splash:go("https://www.taobao.com")
    splash:wait(2)
    return {html=splash:html()}
end

4.3 jsfunc()

> 直接调用JavaScript定义的方法,但是所调用的方法需要用双中括号包围,这相当于实现了JavaScript方法到Lua脚本的转换

function main(splash, args)
  splash:go("http://www.sxt.cn")
  local scroll_to = splash:jsfunc("window.scrollTo")
  scroll_to(0, 300)
  return {png=splash:png()}
end

4.4 evaljs()与 runjs()

  • - evaljs() 以执行JavaScript代码并返回最后一条JavaScript语句的返回结果
  • - runjs() 以执行JavaScript代码,它与evaljs()的功能类似,但是更偏向于执行某些动作或声明某些方法
function main(splash, args)
  splash:go("https://www.baidu.com")
  splash:runjs("foo = function() { return 'sxt' }")
  local result = splash:evaljs("foo()")
  return result
end

4.5 html()

> 获取网页的源代码

function main(splash, args)
  splash:go("https://www.bjsxt.com")
  return splash:html()
end

4.6 png()

> 获取PNG格式的网页截图

function main(splash, args)
  splash:go("https://www.bjsxt.com")
  return splash:png()
end

4.7 har()

> 获取页面加载过程描述

function main(splash, args)
  splash:go("https://www.bjsxt.com")
  return splash:har()
end

4.8 url()

> 获取当前正在访问的URL

function main(splash, args)
  splash:go("https://www.bjsxt.com")
  return splash:url()
end

4.9 get_cookies()

> 获取当前页面的Cookies

function main(splash, args)
  splash:go("https://www.bjsxt.com")
  return splash:get_cookies()
end

4.10 add_cookie()

> 当前页面添加Cookie

cookies = splash:add_cookie{name, value, path=nil, domain=nil, expires=nil, httpOnly=nil, secure=nil}
function main(splash)
    splash:add_cookie{"sessionid", "123456abcdef", "/", domain="http://bjsxt.com"}
    splash:go("http://bjsxt.com/")
    return splash:html()
end

4.11 clear_cookies()

> 可以清除所有的Cookies

function main(splash)
    splash:go("https://www.bjsxt.com/")
    splash:clear_cookies()
    return splash:get_cookies()
end

4.12 set_user_agent()

> 设置浏览器的User-Agent

function main(splash)
  splash:set_user_agent('Splash')
  splash:go("http://httpbin.org/get")
  return splash:html()
end

4.13 set_custom_headers()

> 设置请求头

function main(splash)
  splash:set_custom_headers({
     ["User-Agent"] = "Splash",
     ["Site"] = "Splash",
  })
  splash:go("http://httpbin.org/get")
  return splash:html()
end

4.14 select()

> 选中符合条件的第一个节点

> 如果有多个节点符合条件,则只会返回一个

> 其参数是CSS选择器

function main(splash)
  splash:go("https://www.baidu.com/")
  input = splash:select("#kw")
  splash:wait(3)
  return splash:png()
end

4.15 send_text()

> 填写文本

function main(splash)
  splash:go("https://www.baidu.com/")
  input = splash:select("#kw")
  input:send_text('Splash')
  splash:wait(3)
  return splash:png()
end

4.16 mouse_click()

> 模拟鼠标点击操作

function main(splash)
  splash:go("https://www.baidu.com/")
  input = splash:select("#kw")
  input:send_text('Splash')
  submit = splash:select('#su')
  submit:mouse_click()
  splash:wait(3)
  return splash:png()
end

5 Splash与Python结合

5.1 render.html

> 此接口用于获取JavaScript渲染的页面的HTML代码,接口地址就是Splash的运行地址加此接口名称,例如`http://192.168.99.100:8050/render.html`

import requests
url = 'http://192.168.99.100:8050/render.html?url=https://www.bjsxt.com&wait=3'
response = requests.get(url)
print(response.text)

5.2 render.png

> 此接口可以获取网页截图

import requests
 
url = 'http://192.168.99.100:8050/render.png?url=https://www.jd.com&wait=5&width=1000&height=700'
response = requests.get(url)
with open('taobao.png', 'wb') as f:
    f.write(response.content)

5.3 execute

> 最为强大的接口。前面说了很多Splash Lua脚本的操作,用此接口便可实现与Lua脚本的对接

import requests
from urllib.parse import quote
 
lua = '''
function main(splash)
    return 'hello'
end
url = 'http://192.168.99.100:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
print(response.text)

本文分享自微信公众号 - 离不开的网(Gy_dxj)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-06-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端下午茶

《你不知道的JavaScript》 (中) 阅读摘要

本书属于基础类书籍,会有比较多的基础知识,所以这里仅记录平常不怎么容易注意到的知识点,不会全记,供大家和自己翻阅;

8310
来自专栏快乐学Python

Vue 终级前后端分离方案 —— Vue 使用 axios 访问 API

有很多时候你在构建应用时需要访问一个 API 并展示其数据。做这件事的方法有好几种,而使用基于 promise 的 HTTP 客户端 axios 则是其中非常流...

18030
来自专栏前端下午茶

[译] 网速敏感的视频延迟加载方案

一个大视频的背景,如果做的好,会是一个绝佳的体验!但是,在首页添加一个视频并不仅仅是随便找个人,然后加个 25mb 的视频,那会让你的所有的性能优化都付之一炬。

11030
来自专栏灵魂画师牧码

画解算法:70. 爬楼梯

https://leetcode-cn.com/problems/climbing-stairs/

10920
来自专栏后端开发随笔

Docker实践之02-使用镜像及定制

Docker运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker会从镜像仓库下载该镜像。 从Docker镜像仓库获取镜像的命令是docker ...

12260
来自专栏灵魂画师牧码

画解算法:66. 加一

https://leetcode-cn.com/problems/plus-one/

15130
来自专栏晏霖

CountDownLatch讲解-Junit实现多线程测试

我们知道使用junit进行多线程测试时,主线程执行完毕后直接结束所有线程,(这就好比我前文说线程五种状态中的“STOP”,就是不接受新任务,中断当前正在运行的任...

10820
来自专栏后端开发随笔

在日志中记录Java异常信息的正确姿势

今天遇到一个线上的BUG,在执行表单提交时失败,但是从程序日志中看不到任何异常信息。 在Review源代码时发现,当catch到异常时只是输出了e.getMe...

14630
来自专栏快乐学Python

编程用Hyper终端配置口袋妖怪皮卡丘主题

现在给大家介绍一款漂亮的命令行工具,基于 Electron 啥系统都支持都能用的跨平台终端——Hyper Terminal

14130
来自专栏灵魂画师牧码

画解算法:27. 移除元素

https://leetcode-cn.com/problems/remove-element/

11120

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励