Splash的使用
Splash
是一个JS
渲染服务,本质是一个轻量级浏览器.建议Splash
通过Docker
安装.
Lua脚本
进入Splash,能看见这样一段代码:
function main(splash, args)
assert(splash:go(args.url))
assert(splash:wait(0.5))
return {
html = splash:html(),
png = splash:png(),
har = splash:har(),
}
end
大致能看明白这段代码先执行了go
方法,然后wait
,返回值是html
,png
,har
.
因此,通过修改这段代码,能实现更多的功能,具体细节请看笔者的Lua语言总结
入口和返回值
入口:
函数的入口固定为main
,和c
差不多返回值:
返回值可以是字符串,也可以是字典,其形式分别如下:function main(splash, args) return `Hello World!` //字符串 end function main(splash, args) return {hello=`Hello World!`} //字典 end
异步处理
splash
支持异步处理,在wait
的时候会进行其他任务function main(splash, args) local urls = {"www.baidu.com","www.google.com","www.chrome.com"} local results = {} for index,url in pairs(urls) do local ok,reason = splash:go(url) if ok then splash.wait(2) results[url] = splash.png() end end return results end
splash对象的属性
main
方法中的第一个参数splash
及其重要,类似selenium
中的webdriver
对象.
args属性
main
方法中的第二个参数args
也是splash
的args
属性,所以:
function main(splash)
local args = splash.args
end
也是正确的.
该属性可用于获取加载时的配置参数,例如url
,对于POST
请求可获取提交的表单,GET
请求能获取请求参数.
js_enable属性
是否执行js
的开关
recource_timeout属性
设置页面加载的超时时间,单位为秒
,设置为0
和nil
表示不检测超时
images_enable属性
用于设置是否加载图片,默认为true
,如果不加载,可提高页面加载速度,但也可能影响js
渲染.
plugins_enable属性
用于控制是否开启浏览器插件(比如时代眼泪Flash),默认不开启.
scroll_position属性
控制页面上下滚动或左右滚动
function main(splash)
assert(splash:go(url))
splash.scroll_position = {y=400} --控制上下滚动的像素为400
return {png = splash.png()}
end
splash对象的方法
go方法
该方法用于请求某个链接,用于模拟GET请求和POST请求,同时支持传入请求头,表单等数据
ok,reason = splash:go(url,baseurl = nil, headers = nil, http_method = "GET", body = nil, formdata = nil)
- url:请求的URL
- baseurl: 资源加载的相对路径,可选参数
- headers: 请求头
- http_methos:请求方法,默认是
GET
,支持POST
- body:
POST
方法时的表单数据,Content-type
为application/json
- formdata:
POST
方法时的表单数据,使用的Content-type
为application/x-www-form-urlencoded
ok
表示是否请求成功,如果失败,则ok
为空,reason
存储失败的原因
wait方法
该方法用于控制页面等待时间,用法如下:
ok,reason = splash:wait(time, cancel_on_redirect=false,concel_on_error=true)
- time:等待时间,单位秒
- cancel_on_redirect: 如果发生重定向则停止等待,并返回重定向结果,可选参数,默认为false
- cancel_on_error:如果页面加载错误就停止等待,可选参数,默认为false
返回值和go
方法类似,不再赘述
jsfunc方法
该方法直接调用JavaScript
定义的方法,但是需要用双中括号把调用的方法扩起来.实现js
方法和lua
方法的转换,示例如下
function main(splash)
local get_div_num = splash:jsfunc([[
function () {
var body = document.body;
var divs = body.getElementByTagName("div");
return divs.length;
}
]])
splash:go(url)
return get_div_num();
end
evaljs方法
此方法用于执行js
代码并返回最后一条js
代码的返回结果,示例如下:
local title = splash:evaljs("document.title")
runjs方法
此方法也是用于执行js
代码,和evaljs
类似,但是其更偏向于执行某些动作或声明某些方法,示例如下:
local title = splash:runjs("foo = function(){return 'bar'}");
html方法
获取爬取页面的html
源代码
png方法
获取爬取页面的png
格式截屏
jpeg方法
获取JPEG
格式的页面截屏
har方法
此方法用于获取页面加载过程中的描述信息.
url方法
用于获取当前正在访问网页的url
.
set_user_agent方法
此方法用于设置浏览器的User-Agent
select方法
此方法用于选中符合条件的第一个节点
,语法和css
选择器类似
function main(splash)
splash:go("www.baidu.com")
input = splash:select("#kw") --id 为 kw 的节点
return splash:text();
end
select_all方法
此方法返回所有符合条件的节点
mouse_click方法
相当于selenium
的click
方法
send_text方法
相当于selenium
的send_keys
方法
调用Splash提供的Api
前面是lua
脚本得用法,但是要实现Splash
渲染页面,和python
交互获得我们想要的东西,因此,需要调用splash
提供的api
.api
地址格式是:http://localhost:8050/{api}?url={}
render.html
api
地址是:http://localhost:8050/render.html?url={}
实例如下:
import requests
url = "https://www.baidu.com"
base_url = "http://localhost:8050/render.html?url={}"
response = requests.get(base_url.format(url))
print(response.text)
render.png
api
地址是:http://localhost:8050/render.png?url={}&width={}&height={}
其中width
和height
用于控制截图的长宽.
render.jpeg
和render.png
类似
render.har
用于获取HAR
数据返回值是json
数据
render.json
此API
包含前面所有API
的功能,基础功能为返回json
格式的请求数据,通过增加不同的参数返回不同的结果.http://localhost:8050/render.json?url=www.baidu.com&html=1
,增加返回html代码的功能
execute
该方法的api
为:
http://localhost:8050/execute?lua_source={}
实例如下:
import requests
from urllib.parse import quote
lua = """
function main(splash)
local get_div_num = splash:jsfunc([[
function () {
var body = document.body;
var divs = body.getElementByTagName("div");
return divs.length;
}
]])
splash:go(url)
return get_div_num();
end
"""
base_url = "http://localhost:8050/execute?lua_source="
url = base_url + quote(lua)
response = requests.get(url)
print(response.text())