Splash的使用
目标:作为Selenium的备选方案,加载js渲染后的浏览器数据
安装方法:https://blog.csdn.net/weixin_40743639/article/details/122833394?spm=1001.2014.3001.5501
或者,https://cuiqingcai.com/31071.html
一. 实例引入
function main(splash, args)
assert(splash:go(args.url)) -- 访问args.url页面
assert(splash:wait(0.5)) -- 异步等待0.5秒
return {
html = splash:html(), -- 返回js渲染后的html代码
png = splash:png(), -- 返回js渲染后的png图像
har = splash:har() -- 返回页面访问的抓包情况
}
end
二. Splash Lua脚本
2.1 入口及返回值
-- 返回字典形式的HTTP响应
function main(splash, args)
splash:go('http://www.baidu.com') -- 访问百度
splash:wait(0.5) -- 异步等待0.5秒
local title = splash:evaljs('document.title') -- 执行js语句
return {title=title} -- 结果以字典形式返回
end
-- 返回字符串形式的HTTP响应
function main(splash, args)
splash:go('http://www.baidu.com') -- 访问百度
splash:wait(0.5) -- 异步等待0.5秒
local title = splash:evaljs('document.title') -- 执行js语句
return title -- 结果以字符串形式返回
end
2.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 -- lua的for循环遍历,详情参考菜鸟教程lua语法
local ok, reason = splash:go('http://'..url) -- lua的字符串连接用的 .. 运算符
if ok then
splash:wait(2) -- 异步等待2秒
results[url] = splash:png() -- results表中添加返回的png结果
end
end
return results -- 结果返回
end
三. splash对象的属性
3.1 args属性
-- 获取url的方式1
function main(splash, args)
local url = args.url
end
-- 获取url的方式2
function main(splash, args)
local url = splash.args.url
end
3.2 js_enable属性
function main(splash, args)
splash:go('https://www.baidu.com')
splash.js_enabled = false -- 默认是true,可以运行js
local title = splash:evaljs('document.title') -- js运行失败
return {title=title} -- 结果返回错误
end
3.3 resource_timout属性
function main(splash, args)
splash.resource_timeout = 0.1 -- 默认是0,没有超时时间
splash:go('https://www.taobao.com') -- 上面修改成0.1后,超过0.1秒没返回就会报错
return splash:html()
end
3.4 images_enable属性
function main(splash, args)
splash.images_enabled = false -- 默认是true,可以加载图像
assert(splash:go('https://www.jd.com')) -- 访问京东
return {
png = splash:png() -- 上面设置了禁止加载图片,因此返回内容中没图像
}
end
3.5 scroll_position属性
function main(splash, args)
assert(splash:go('https://www.taobao.com')) -- 访问淘宝
splash.scroll_position = {
y = 400 -- 滚动条拖400像素
}
return {
png = splash:png() -- 返回滚动条拖动后的效果
}
end
四. splash对象的方法
4.1 go方法
function main(splash, args)
local ok, reason = splash:go{
'http://www.httpbin.org/post',
http_method = 'POST', -- 指定方法为POST方法
body = 'name=Germey' -- 提交的表单数据,Content-type为application/json
}
if ok then
return splash:html() -- 如果正确访问,则返回html代码
end
end
4.2 wait方法
function main(splash, args)
splash:go('https://www.taobao.com') -- 访问淘宝
splash:wait(2) -- 异步等待2秒
return {
html = splash:html() -- 返回html代码
}
end
4.3 jsfunc方法 —— 用于从lua中定义js函数,并赋值给lua变量
function main(splash, args)
-- 定义一个js的匿名函数,把它赋值给lua中的变量
local get_div_count = splash:jsfunc([[
function() {
var body = document.body;
var divs = body.getElementsByTagName('div')
return divs.length;
}
]])
splash:go('https://www.baidu.com')
return ('There are %s DIVs'):format(get_div_count())
end
更多从JavaScript方法转换到Lua脚本的细节,参考官方文档:
https://splash.readthedocs.io/en/stable/scripting-ref.html#splash-jsfunc
4.4 evaljs方法 —— 用于执行js代码,并获取起返回值
function main(splash, args)
splash:go('http://www.baidu.com') -- 访问百度
splash:wait(0.5) -- 异步等待0.5秒
local title = splash:evaljs('document.title') -- 执行js语句,返回值给lua变量
return {
title = title
}
end
4.5 runjs方法 —— 在Js环境下执行代码,但不返回值,需要返回值通过evaljs获取
function main(splash, args)
splash:go('https://www.baidu.com') -- 访问百度
splash:runjs("foo = function() {return 'bar'}") -- 进入js环境,执行js代码
local result = splash:evaljs("foo()") -- 执行js代码,获取js的返回值
return result
end
4.6 html方法
function main(splash, args)
splash:go('https://httpbin.org/get') -- 访问http测试接口网页
return splash:html() -- 返回html
end
4.7 png方法和jpeg方法
function main(splash, args)
splash:go('https://www.taobao.com') -- 访问淘宝
return splash:png() -- 返回png形式的结果
end
function main(splash, args)
splash:go('https://www.taobao.com') -- 访问淘宝
return splash:jpeg() -- 返回jpeg形式的结果
end
4.8 har方法
function main(splash, args)
splash:go('https://www.baidu.com') -- 访问百度
return splash:har() -- 返回抓包情况
end
4.9 url方法
function main(splash, args)
splash:go('https://www.baidu.com') -- 访问淘宝
return splash:url() -- 返回访问的url
end
4.10 set_user_agent方法
function main(splash, args)
splash:set_user_agent('Splash') -- 设置User-Agent代理
splash:go('http://www.httpbin.org/get') -- 访问http测试接口网页
return splash:html() -- 返回html代码
end
4.11 select方法
function main(splash, args)
splash:go('https://www.baidu.com/') -- 访问百度
input = splash:select('#kw') -- 用css选择器找到输入文本框
input:send_text('Splash') -- 输入Splash
splash:wait(3) -- 异步等待3秒
return splash:png() -- 返回浏览器的png结果
end
4.12. select_all方法
function main(splash, args)
local treat = require('treat')
assert(splash:go('http://quotes.toscrape.com/')) -- 访问页面
assert(splash:wait(0.5)) -- 异步等待0.5秒
local texts = splash:select_all('.quote .text') -- 用css选择器找到所有.quote .text标签
local results = {}
for index, text in ipairs(texts) do -- 循环遍历找到的节点标签
results[index] = text.node.innerHTML -- 获取里面的html代码
end
return treat.as_array(results)
end
4.13 mouse_click方法
function main(splash, args)
splash:go('https://www.baidu.com/') -- 访问百度
input = splash:select('#kw') -- 用css选择器找到输入文本框
input:send_text('Splash') -- 输入Splash
splash:wait(3) -- 异步等待3秒
submit = splash:select('#su') -- 用css选择器找到id为su的按钮
submit:mouse_click() -- 模拟鼠标点击
splash:wait(5) -- 异步等待5秒
return splash:png() -- 返回搜索的结果,以png形式
end
更多对象的常用方法参考官方文档:
https://splash.readthedocs.io/en/stable/scripting-ref.html
更多针对页面元素的方法参考官方文档:
https://splash.readthedocs.io/en/stable/scripting-element-object.html
五. Splash提供的API接口
5.1 render.html接口
import re
import requests
url = 'http://192.168.63.128:8050/render.html?url=https://www.taobao.com&wait=5'
response = requests.get(url)
print(response.text)
render.html接口支持设置代理,图片加载,请求头,请求方法等设置,参考官方文档:
https://splash.readthedocs.io/en/stable/api.html#render-html
5.2 render.png接口
import requests
url = 'http://192.168.63.128:8050/render.png?url=https://www.jd.com&wait=5&width=1000&height=700'
response = requests.get(url)
with open('jd.png', 'wb') as f:
f.write(response.content)
更多内容参考官方文档:
https://splash.readthedocs.io/en/stable/api.html#render-png
5.3 execute接口
import requests
from urllib.parse import quote
lua = '''
function main(splash, args)
local treat = require('treat')
local response = splash:http_get('http://www.httpbin.org/get')
return {
html=treat.as_string(response.body),
url=response.url,
status=response.status
}
end
'''
url = 'http://192.168.63.128:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
print(response.text)