## 1.说明
Lua脚本语法:[http://www.runoob.com/lua/lua-basic-syntax.html](http://www.runoob.com/lua/lua-basic-syntax.html)
Lua下载:[https://github.com/rjpcomputing/luaforwindows/releases](https://github.com/rjpcomputing/luaforwindows/releases)
官方文档:
* [https://splash.readthedocs.io/en/stable/scripting-ref.html](https://splash.readthedocs.io/en/stable/scripting-ref.html)
* [https://splash.readthedocs.io/en/stable/scripting-element-object.html](https://splash.readthedocs.io/en/stable/scripting-element-object.html)
* [https://splash.readthedocs.io/en/stable/api.html\#render-json](https://splash.readthedocs.io/en/stable/api.html#render-json)
* [https://splash.readthedocs.io/en/stable/api.html\#render-png](https://splash.readthedocs.io/en/stable/api.html#render-png)
* [https://splash.readthedocs.io/en/stable/api.html\#render-html](https://splash.readthedocs.io/en/stable/api.html#render-html)
### 2.实例
![](/assets/7.2.2.png)
脚本语言内容:
```
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
```
wait\(\):等待
html:返回页面的源码
png:返回页面的截图
HAR:返回页面的HAR信息
### 3.Splash Lua脚本
#### 入口及返回值
```
function main(splash, args)
assert(splash:go("https://www.baidu.com"))
assert(splash:wait(0.5))
local title = splash:evaljs("document.title")
return {
title = title
}
end
```
通过spalsh:evaljs\(\)方法传入javascript脚本
Splash默认调用main\(\)方法
方法的返回值为字典形式或者是字符串形式,最后都会转化为一个Splash HTTP Response
```
function main(splash, args)
return {
hello = "world"
}
end
```
#### 异步处理
```
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
```
![](/assets/7.2.3.png)
wait\(\):等待的描述
..:字符串拼接操作符
ipairs\(\):操作字典进行迭代
#### 4.Splash对象属性
#### args
splash对象的args属性可以获取加载时配置的参数
```
function main(spalsh,args)
local url = args.url
return url
end
```
运行结果:
```
Splash Response: "https://www.qidian.com/"
```
#### js\_endabled
js\_endabled属性是splash的javascript执行开关,可以将其配置为True或False来控制是否可以执行JavaScript代码,默认为True
```
function main(splash,args)
splash:go(args.url)
splash.js_enabled = false
local title = splash:evaljs("document.title")
return {
title = title,
}
end
```
禁用之后,调用evaljs\(\)方法执行javascript代码,会抛出异常
```
{
"description": "Error happened while executing Lua script",
"info": {
"message": "[string \"function main(splash,args)\r...\"]:4: unknown JS error: None",
"line_number": 4,
"source": "[string \"function main(splash,args)\r...\"]",
"splash_method": "evaljs",
"type": "JS_ERROR",
"error": "unknown JS error: None",
"js_error_message": null
},
"error": 400,
"type": "ScriptError"
}
```
一般情况下默认开启
#### resoure\_timeout
设置加载的超时时间,单位为秒数。如果设置为0或nil就表示不检测超时
```
function main(splash,args)
splash.resource_timeout = 0.1
splash:go(args.url)
return splash:png()
end
```
设置超时为0.1秒,如果在0.1秒之内没有得到响应就会抛出异常
![](/assets/7.2.4.png)
### images\_enabled
设置图片是否加载
```
function main(splash,args)
splash.images_enabled = false
splash:go(args.url)
return splash:png()
end
```
#### plugins\_enabled
控制浏览器插件是否开启,如Flash。默认情况下事是False/不开启
```
splash.plugins_enabled = flase/true
```
#### scroll\_position
控制页面的滚动偏移
splash.scroll\_position = {x=x,y=y}
```
function main(splash,args)
splash.images_enabled = true
splash:go(args.url)
splash:wait(3)
splash.scroll_position = {y=200}
return splash:png()
end
```
### 5.Splash对象方法
#### go\(\)
go\(\):用来请求某个链接的方法,可以模拟GET和POST请求,同时支持传入Headers、From Data等数据
```
ok, reason = splash:go{url, baseurl=nil, headers=nil, http_method="GET", body=nil, formdata=nil}
```
参数说明:
* url:请求的url
* baseurl:资源加载相对路径
* headers:请求的headers
* http\_method:默认是get,同时支持post
* body:post的时候的表单数据,使用的Content-type为application
* fromdata:post的时候表单数据,使用的Content-type为application/x-www-form-urlencoded
返回的结果是结果ok和原因reason的组合,如果ok为空,代表网页加载出现了错误,此时reason变量中包含了错误的原因,否则证明页面加载成功
```
function main(splash,args)
local ok,reason = splash:go{"http://httpbin.org/post",http_method="POST",body="name-Germey"}
if ok then
return splash:html()
end
end
```
模拟post请求,并传入POST的表单数据,如果成功,则返回用页面源代码
运行结果:
```
<html><head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">{
"args": {},
"data": "",
"files": {},
"form": {
"name-Germey": ""
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en,*",
"Connection": "close",
"Content-Length": "11",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"Origin": "null",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/9.0 Safari/602.1"
},
"json": null,
"origin": "58.16.27.216",
"url": "http://httpbin.org/post"
}
</pre></body></html>
```
#### wait\(\)
控制页面等待时间
```
ok,reason = splash:wait(time,cancel_on_redirect=false,cancle_on_error=True)
```
参数说明:
* time:等待秒数
* cancel\_on\_redirect:默认Fasle,如果发生了重定向就停止等待,并返回重定向结果
* cancel\_on\_error:默认False,如果加载发生了加载错误就停止等待
```
function main(splash,args)
splash:go(args.url)
splash:wait(2)
return splash:html()
end
```
#### jsfunc\(\)
直接调用javascript定义的方法,需要用双中括号包围,相等于实现了javascript方法到lua脚本的转换
```
function main(splash, args)
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
```
运行结果:
```
Splash Response: "There are 23 DIVs"
```
#### evaljs\(\)
执行javascript代码并返回最后一条语句的返回结果
```
result = splash:evaljs(js)
```
#### runjs\(\)
执行JavaScript代码类似于evaljs\(\)功能类似,但偏向于执行某些动作或声明某些方法evaljs\(\)偏向于获取某些执行结果
```
function main(splash,args)
splash:go("https;//www.baidu.com")
splash:runjs("foo = function(){return 'bar'}")
local result = splash:evaljs("foo()")
return result
end
```
运行结果:
```
Splash Response: "bar"
```
#### autoload\(\)
设置每个页面访问时自动加载的对象
```
ok,reason = splash:autoload{source_or_url,source=nil,url=nil}
```
参数说明:
* source\_or\_url:JavaScript代码或者JavaScript库链接
* source,JavaScript代码
* url,JavaScript库链接
只负责加载JavaScript代码或库,不执行任何操作,如果要执行操作可以调用evaljs\(\)或runjs\(\)方法
```
function main(splash,args)
splash:autoload([[
function get_documetn_title(){
return document.title;
}
]])
splash:go("https://www.baidu.com")
return splash:evaljs("get_documetn_title()")
end
```
运行结果:
```
Splash Response: "百度一下,你就知道"
```
加载某些方法库,如JQuery
```
function main(splash,args)
splash:autoload("https://code.jquery.com/jquery-2.1.3.min.js")
splash:go("https://www.baidu.com")
local version = splash:evaljs("$.fn.jquery")
return "JQuery version: " .. version
end
```
运行结果:
```
Splash Response: "JQuery version: 1.10.2"
```
#### call\_later\(\)
可以通过设置定时任务和延迟时间实现任务延时执行,并且可以在执行前通过 cancel\(\) 方法重新执行定时任务
```
function main(splash,args)
local snapshots = {}
local timer = splash:call_later(function()
snapshots['a'] = splash:png()
splash:wait(1.0)
snapshots["b"] = splash:png()
end,0.2)
splash:go("https://www.taobao.com")
splash:wait(3.0)
return snapshots
end
```
![](/assets/7.2.5.png)
#### http\_get\(\) {#httpget}
此方法可以模拟发送 HTTP 的 GET 请求,使用方法如下:
```
response = splash:http_get{url, headers=nil, follow_redirects=true}
```
参数说明如下:
* url,请求URL。
* headers,可选参数,默认为空,请求的 Headers。
* follow\_redirects,可选参数,默认为 True,是否启动自动重定向。
#### http\_post\(\) {#httppost}
和 http\_get\(\) 方法类似,此方法是模拟发送一个 POST 请求,不过多了一个参数 body,使用方法如下
```
response = splash:http_post{url, headers=nil, follow_redirects=true, body=nil}
```
参数说明如下:
* url,请求URL。
* headers,可选参数,默认为空,请求的 Headers。
* follow\_redirects,可选参数,默认为 True,是否启动自动重定向。
* body,可选参数,默认为空,即表单数据。
```
function main(splash, args)
local treat = require("treat")
local json = require("json")
local response = splash:http_post{"http://httpbin.org/post",
body=json.encode({name="Germey"}),
headers={["content-type"]="application/json"}
}
return {
html=treat.as_string(response.body),
url=response.url,
status=response.status
}
end
```
#### set\_content\(\) {#setcontent}
此方法可以用来设置页面的内容
```
function main(splash)
assert(splash:set_content("<html><body><h1>hello Angle</h1></body></html>"))
return splash:png()
end
```
#### html\(\) {#html}
此方法可以用来获取网页的源代码
#### png\(\) {#png}
此方法可以用来获取 PNG 格式的网页截图
#### jpeg\(\) {#jpeg}
此方法可以用来获取 JPEG 格式的网页截图
#### har\(\) {#har}
此方法可以用来获取页面加载过程描述
#### url\(\) {#url}
此方法可以获取当前正在访问的 URL
#### get\_cookies\(\) {#getcookies}
此方法可以获取当前页面的 Cookies
#### add\_cookie\(\) {#addcookie}
此方法可以为当前页面添加 Cookie
```
cookies = splash:add_cookie{name, value, path=nil, domain=nil, expires=nil, httpOnly=nil, secure=nil}
```
```
function main(splash)
splash:add_cookie{"sessionid", "asdadasd", "/", domain="http://example.com"}
splash:go("http://example.com/")
return splash:html()
end
```
#### clear\_cookies\(\) {#clearcookies}
此方法可以清除所有的 Cookies
```
splash:clear_cookies()
```
#### get\_viewport\_size\(\) {#getviewportsize}
此方法可以获取当前浏览器页面的大小,即宽高
#### set\_viewport\_size\(\) {#setviewportsize}
此方法可以设置当前浏览器页面的大小,即宽高
```
spalsh:set_viewport_size(x,y)
```
#### set\_viewport\_full\(\) {#setviewportfull}
此方法可以设置浏览器全屏显示
#### set\_user\_agent\(\) {#setuseragent}
此方法可以设置浏览器的 User-Agent
```
splash:set_user_agent("Splash")
```
#### set\_custom\_headers\(\) {#setcustomheaders}
此方法可以设置请求的 Headers
```
set_custom_headers()
此方法可以设置请求的 Headers
```
#### select\(\) {#select}
select\(\) 方法可以选中符合条件的第一个节点,如果有多个节点符合条件,则只会返回一个,其参数是 CSS 选择器
```
function main(splash,args)
splash:go(args.url)
input = splash:select("#kw")
input:send_text('Splash')
splash:wait(3)
return splash:png()
end
```
![](/assets/7.2.6.png)
#### select\_all\(\) {#selectall}
此方法可以选中所有的符合条件的节点,其参数是 CSS 选择器
```
function main(splash)
local treat = require('treat')
assert(splash:go("http://quotes.toscrape.com/"))
assert(splash:wait(0.5))
local texts = splash:select_all('.quote .text')
local results = {}
for index, text in ipairs(texts) do
results[index] = text.node.innerHTML
end
return treat.as_array(results)
end
```
#### mouse\_click\(\) {#mouseclick}
此方法可以模拟鼠标点击操作,传入的参数为坐标值 x、y,也可以直接选中某个节点直接调用此方法
```
function main(splash,args)
splash:go(args.url)
input = splash:select("#kw")
input:send_text('Splash')
submit = splash:select("#su")
submit:mouse_click()
splash:wait(3)
return splash:png()
end
```
![](/assets/7.2.7.png)
### 6.Splash API调用
### render.html
用于获取javascript渲染页面的HTML代码
```
curl http://localhost:8050/render.html?url=https://www.baidu.com
```
```
import requests
url = "http://192.168.99.100:8050/render.html?url=https://www.baidu.com&wait=5"
response = requests.get(url)
print(response.text)
```
### render.png
获取网页截图
参数:
* height:高
* width:宽
```
curl http://localhost:8050/render.png?url=https://www.taobao.com&wait=5&width=1000&height=700
```
```
import requests
url = "http://192.168.99.100:8050/render.png?url=https://www.taobao.com&wait=10&width=1000&height=700"
response = requests.get(url)
with open('taobao.png','wb') as f:
f.write(response.content)
```
图片:[https://splash.readthedocs.io/en/stable/api.html\#render-png](https://splash.readthedocs.io/en/stable/api.html#render-png)
### render.har {#renderhar}
此接口用于获取页面加载的 HAR 数据
```
curl http://localhost:8050/render.har?url=https://www.jd.com&wait=5
```
返回结果非常多,是一个 Json 格式的数据,里面包含了页面加载过程中的 HAR 数据。
### render.json {#renderjson}
此接口包含了前面接口的所有功能,返回结果是 Json 格式
```
curl http://localhost:8050/render.json?url=https://httpbin.org
```
更多参数:[https://splash.readthedocs.io/en/stable/api.html\#render-json](https://splash.readthedocs.io/en/stable/api.html#render-json)
### execute {#execute}
此接口可以实现和 Lua 脚本的对接
```
function main(splash)
return "hello"
end
```
```
curl http://localhost:8050/execute?lua_source=function+main%28splash%29%0D%0A++return+%27hello%27%0D%0Aend
```
```
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)
```
```
import requests
from urllib.parse import quote
lua = '''
function main(splash, args)
local treat = require("treat")
local response = splash:http_get("http://httpbin.org/get")
return {
html=treat.as_string(response.body),
url=response.url,
status=response.status
}
end
'''
url = 'http://localhost:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
print(response.text)
```
- 介绍
- 1.开发环境配置
- 1.1 python3的安装
- 1.1.1 windows下的安装
- 1.1.2 Linux下的安装
- 1.1.3 Mac下的安装
- 1.2 请求库的安装
- 1.2.1 requests的安装
- 1.2.2 selenium的安装
- 1.2.3 ChromeDriver的安装
- 1.2.4 GeckoDriver 的安装
- 1.2.5 PhantomJS的安装
- 1.2.6 aiohttp的安装
- 1.3 解析库的安装
- 1.3.1 lxml的安装
- 1.3.2 Beautiful Soup的安装
- 1.3.3 pyquery的安装
- 1.3.4 tesserocr的安装
- 1.4 数据库的安装
- 1.4.1 MySQL的安装
- 1.4.2 MongoDB的安装
- 1.4.3 Redis的安装
- 1.5 存储库的安装
- 1.5.1 PyMySQL的安装
- 1.5.2 PyMongo的安装
- 1.5.3 redis-py的安装
- 1.5.4 RedisDump的安装
- 1.6 Web库的安装
- 1.6.1 Flask的安装
- 1.6.2 Tornado的安装
- 1.7 App爬取相关库的安装
- 1.7.1 Charles的安装
- 1.7.2 mitmproxy的安装
- 1.7.3 Appium的安装
- 1.8 爬虫框架的安装
- 1.8.1 pyspider的安装
- 1.8.2 Scrapy的安装
- 1.8.3 Scrapy-Splash的安装
- 1.8.4 ScrapyRedis的安装
- 1.9 布署相关库的安装
- 1.9.1 Docker的安装
- 1.9.2 Scrapyd的安装
- 1.9.3 ScrapydClient的安装
- 1.9.4 ScrapydAPI的安装
- 1.9.5 Scrapyrt的安装
- 1.9.6-Gerapy的安装
- 2.爬虫基础
- 2.1 HTTP 基本原理
- 2.1.1 URI和URL
- 2.1.2 超文本
- 2.1.3 HTTP和HTTPS
- 2.1.4 HTTP请求过程
- 2.1.5 请求
- 2.1.6 响应
- 2.2 网页基础
- 2.2.1网页的组成
- 2.2.2 网页的结构
- 2.2.3 节点树及节点间的关系
- 2.2.4 选择器
- 2.3 爬虫的基本原理
- 2.3.1 爬虫概述
- 2.3.2 能抓怎样的数据
- 2.3.3 javascript渲染的页面
- 2.4 会话和Cookies
- 2.4.1 静态网页和动态网页
- 2.4.2 无状态HTTP
- 2.4.3 常见误区
- 2.5 代理的基本原理
- 2.5.1 基本原理
- 2.5.2 代理的作用
- 2.5.3 爬虫代理
- 2.5.4 代理分类
- 2.5.5 常见代理设置
- 3.基本库使用
- 3.1 使用urllib
- 3.1.1 发送请求
- 3.1.2 处理异常
- 3.1.3 解析链接
- 3.1.4 分析Robots协议
- 3.2 使用requests
- 3.2.1 基本用法
- 3.2.2 高级用法
- 3.3 正则表达式
- 3.4 抓取猫眼电影排行
- 4.解析库的使用
- 4.1 使用xpath
- 4.2 使用Beautiful Soup
- 4.3 使用pyquery
- 5.数据存储
- 5.1 文件存储
- 5.1.1 TXT 文件存储
- 5.1.2 JSON文件存储
- 5.1.3 CSV文件存储
- 5.2 关系型数据库存储
- 5.2.1 MySQL的存储
- 5.3 非关系数据库存储
- 5.3.1 MongoDB存储
- 5.3.2 Redis存储
- 6.Ajax数据爬取
- 6.1 什么是Ajax
- 6.2 Ajax分析方法
- 6.3 Ajax结果提取
- 6.4 分析Ajax爬取今日头条街拍美图
- 7.动态渲染页面爬取
- 7.1 Selenium的使用
- 7.2 Splash的使用
- 7.3 Splash负载均衡配置
- 7.4 使用selenium爬取淘宝商品
- 8.验证码的识别
- 8.1 图形验证码的识别
- 8.2 极验滑动验证码的识别
- 8.3 点触验证码的识别
- 8.4微博宫格验证码的识别
- 9.代理的使用
- 9.1 代理的设置
- 9.2 代理池的维护
- 9.3 付费代理的使用
- 9.4 ADSL拨号代理
- 9.5 使用代理爬取微信公总号文章
- 10.模拟登录
- 10.1 模拟登陆并爬去GitHub
- 10.2 Cookies池的搭建
- 11.App的爬取
- 11.1 Charles的使用
- 11.2 mitmproxy的使用
- 11.3 mitmdump“得到”App电子书信息
- 11.4 Appium的基本使用
- 11.5 Appnium爬取微信朋友圈
- 11.6 Appium+mitmdump爬取京东商品
- 12.pyspider框架的使用
- 12.1 pyspider框架介绍
- 12.2 pyspider的基本使用
- 12.3 pyspider用法详解
- 13.Scrapy框架的使用
- 13.1 scrapy框架介绍
- 13.2 入门
- 13.3 selector的用法
- 13.4 spider的用法
- 13.5 Downloader Middleware的用法
- 13.6 Spider Middleware的用法
- 13.7 Item Pipeline的用法
- 13.8 Scrapy对接Selenium
- 13.9 Scrapy对接Splash
- 13.10 Scrapy通用爬虫
- 13.11 Scrapyrt的使用
- 13.12 Scrapy对接Docker
- 13.13 Scrapy爬取新浪微博
- 14.分布式爬虫
- 14.1 分布式爬虫原理
- 14.2 Scrapy-Redis源码解析
- 14.3 Scrapy分布式实现
- 14.4 Bloom Filter的对接
- 15.分布式爬虫的部署
- 15.1 Scrapyd分布式部署
- 15.2 Scrapyd-Client的使用
- 15.3 Scrapyd对接Docker
- 15.4 Scrapyd批量部署
- 15.5 Gerapy分布式管理
- 微信公总号文章实战
- 源码
- other