简介
splash 能够执行用 Lua 编写的自定义脚本,这能使splash成为和 PhantomJS 相似的 browser automation tool 。
如果想要执行一个脚本并获得结果,可以使用 lua_source 参数发送脚本至 execute 或者 run 。
以下内容通过 execute 实现。
Note:大多数时候,即使你不会 Lua 你也能实现下面的 Splash 脚本。然而,这门语言是值得学习的。你可以用 Lua 编写 Redis、Nginx、Apache、魔兽世界脚本、使用 Corona 创建移动端app,以及使用最先进的深度学习框架 Torch7。Lua 很容学习,推荐一些资料:Learn Lua in 15 minutes 和 Programming in Lua 。
让我们从下面的例子开始吧:
function main(splash, args) splash:go("http://example.com") splash:wait(0.5) local title = splash:evaljs("document.title") return {title=title} end
如果我们通过参数 lua_source 向 execute 端点提交了这脚本,Splash 将先访问 example.com ,等待直到加载,再等待 0.5s ,然后获取页面的 title ,最后将结果封装成JSON对象返回。
Note:Splash UI 还提供了一种简单的测试脚本的方法,访问 http://127.0.0.1:8050/ ,在代码编辑器里编辑 Lua 然后点击 “render me”。为了在splash中运行脚本,你需要弄清楚如何通过你的程序环境向Splash发送HTTP请求。可以查阅这个文档 How to send requests to Splash HTTP API? ,python + request 如何实现在这里有做说明。
Entry Point: the “main” Function
脚本中必须包含一个名为 main 的函数,它返回一个HTTP响应。脚本中可以包含其他辅助函数,但 main 是必须的。
上面的例子中,main返回了一个 Lua table (关联数组,类似python的字典),Lua table会被封装为JSON返回。
main也可以返回一个字符串:
function main(splash) return 'hello' end
字符串会被原样返回,不像Lua table会被封装为JSON。
$ curl 'http://127.0.0.1:8050/execute?lua_source=function+main%28splash%29%0D%0A++return+%27hello%27%0D%0Aend' hello
main 函数接收一个对象,所有的Splash特性都可以通过这个对象访问。我们通常约定这个对象的名字为:splash,但是你也可以不尊从这个约定:
function main(please) please:go("http://example.com") please:wait(0.5) return "ok" end
Where Are My Callbacks?
以下是第一个例子中的部分代码:
splash:go("http://example.com") splash:wait(0.5) local title = splash:evaljs("document.title")
这段代码看起来是标准的流程式代码,没有回调,也没有复杂的 control-flow 结构。但这并不意味着 Splash 使用 同步 方式运转,相反它是异步的。在这段程序中,当执行到 splash:wait(0.5) 时,splash会切换,去执行其他任务,0.5s 后再回来执行接下来的代码。
我们可以在splash脚本中使用 循环、条件判断、函数:
function main(splash, args) splash:set_viewport_size(800, 600) splash:set_user_agent('Splash bot') local example_urls = {"www.google.com", "www.bbc.co.uk", "scrapinghub.com"} local urls = args.urls or example_urls local results = {} for _, url in ipairs(urls) do local ok, reason = splash:go("http://" .. url) if ok then splash:wait(0.2) results[url] = splash:png() end end return results end
查看Splash Lua API 特性:Splash Lua API Overview
Living Without Callbacks
这一段看不懂
Calling Splash Methods
Lua 通常使用 ' : ' 来调用对象的方法,例如调用splash的方法:splash:foo() 。
在splash脚本中调用 Lua method 主要有以下两种方式:
- 参数为 位置参数时:splash:foo(val1, val2)
- 参数为 关键字参数时:splash:foo{name1=val1, name2=val2}
- 参数既有关键字参数,又有位置参数时:splash:foo{val1, name2=val2}
-- Examples of positional arguments: splash:go("http://example.com") splash:wait(0.5, false) local title = splash:evaljs("document.title") -- The same using keyword arguments: splash:go{url="http://example.com"} splash:wait{time=0.5, cancel_on_redirect=false} local title = splash:evaljs{source="document.title"} -- Mixed arguments example: splash:wait{0.5, cancel_on_redirect=false}
为了方便,splash 的方法被设计成既可以通过位置参数调用,也可以通过命名参数调用。但是由于 Lua 中没有真正意义上的命名参数,所以大多数方法都仅支持位置参数。
Error Handling
Lua 有两种报错的方法:raise an exception and return an error flag,see: http://www.lua.org/pil/8.3.html.
splash 使用以下约定:
- 由于开发者而报错,这个错误将被抛出。例如:参数不正确。
- 不是开发者引起的,则返回状态标记,例如:请求网页没有响应。functions that can fail return
ok, reasonpairs.
如果 main 函数引发了一个未处理的异常,splash 将返回 HTTP 400 。
你也可以使用 Lua 的 error 方法,手动抛出异常:
error("A message to be returned in a HTTP 400 response")
可以使用 pcall 方法处理 Lua 异常,查看文档
可以使用 assert 方法将 “status flag” errors 转变为异常。例如,你想让网站不用手动处理任何异常的工作,可以使用 assert 停止处理,并返回 HTTP 400,如果错误级别是 wrong:
local ok, msg = splash:go("http://example.com") if not ok then -- handle error somehow, e.g. error(msg) end -- a shortcut for the code above: use assert assert(splash:go("http://example.com"))
Sandbox
默认情况下,splash脚本是在受限制的环境中执行的:并不是所有标准的Lua模块和函数都可用,Lua require是受限制的,并且有资源限制(尽管相当宽松)。
当sandbox被禁用时,所有的 lua 模块就都可以使用.
在启动 splash 时禁用 sandbox:
$ docker run -it -p 8050:8050 scrapinghub/splash --disable-lua-sandbox
Timeouts
默认情况下,splash脚本的执行超时时间为30s 。
通过 I’m getting lots of 504 Timeout errors, please help! 和 2. Splash Lua script does too many things 查阅更多信息
浙公网安备 33010602011771号