JavaScript动态渲染页面爬取之Splash
Splash是一个 JavaScript渲染服务,是一个含有 HTTP API的轻量级浏览器,它还对接了 Python 中的 Twisted 库和 OT库。利用它,同样可以爬取动态渲染的页面。
功能介绍
利用 Splash,可以实现如下功能:
- 异步处理多个网页的渲染过程:
- 获取渲染后页面的源代码或截图;
- 通过关闭图片渲染或者使用 Adblock规则的方式加快页面渲染的速度;
- 执行特定的 JavaScript 脚本;
- 通过 Lua 脚本控制页面的渲染过程;
- 获取页面渲染的详细过程并以HAR(HTTPArchive)的格式呈现出来。
接下来,我们一起了解 Splash 的具体用法。
准备工作
请确保 Splash 已经正确安装好并可以在本地 8050端口上正常运行。安装方法可以参考 https:/setup.
scrape.center/splash。
win10 docker安装
- 去docker官网下载,但请一定要注意你Windows笔记本电脑版本一定要和docker匹配,否则会报错:

- 查看自己windows版本
检查 Windows 版本:按 Win + R 键,输入 winver,然后点击“确定”。这将显示一个窗口,其中包含您当前使用的 Windows 版本信息。

-
官网找一个合适的版本,一般历史版本可能官网不好找,点击这里找个适合的版本 下载。
-
安装包下载之后直接双击安装即可,不过可能会报错:

-
去给出的网址下载WSL2,安装即可。
splash安装
有了 Docker,只需要一键启动 Splash 即可,命令如下:
docker run -p 8050:8050 scrapinghub/splash
问题1:
docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded.
我们可以配置国内的镜像,尽可能把所有的镜像都配置上,否则不是慢就是依然下载不下来:
"registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn","https://cr.console.aliyun.com","https://mirror.ccs.tencentyun.com","https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn/","https://yxzrazem.mirror.aliyuncs.com","https://docker.kubesre.xyz","https://dc.j8.work","https://docker.registry.cyou","https://docker.hlyun.org","https://docker.chenby.cn","https://docker.jsdelivr.fyi","https://docker-mirrors.mjjman.com","https://docker.kubesre.xyz","https://huecker.io","https://dockerhub.timeweb.cloud","https://docker.registry.cyou","https://docker-cf.registry.cyou","https://dockercf.jsdelivr.fyi","https://dockertest.jsdelivr.fyi","https://2a6bf1988cb6428c877f723ec7530dbc.mirror.swr.myhuaweicloud.com","https://docker.m.daocloud.io","https://hub-mirror.c.163.com","https://mirror.baidubce.com","https://your_preferred_mirror","https://dockerhub.icu","https://docker.registry.cyou","https://docker-cf.registry.cyou","https://dockercf.jsdelivr.fyi","https://docker.jsdelivr.fyi","https://dockertest.jsdelivr.fyi","https://mirror.aliyuncs.com","https://dockerproxy.com","https://mirror.baidubce.com","https://docker.m.daocloud.io","https://docker.nju.edu.cn","https://docker.mirrors.sjtug.sjtu.edu.cn","https://docker.mirrors.ustc.edu.cn","https://mirror.iscas.ac.cn","https://docker.rainbond.cc"]
经过我的测试,发现下载到一半依然报错,于是只能用VPN去下载了。
安装完成之后会有类似的输出结果:

这时我们打开:http://localhost:8050 即可看到 Splash 的主页,如图所示:

当然 Splash 也可以直接安装在远程服务器上,我们在服务器上运行以守护态运行 Splash 即可,命令如下:
docker run -d -p 8050:8050 scrapinghub/splash
在这里多了一个 -d 参数,它代表将 Docker 容器以守护态运行,这样在中断远程服务器连接后不会终止 Splash 服务的运行。
实例引入
上面我们打开http://localhost:8050 即可看到 Splash 的主页,右侧呈现的是一个渲染示例,可以看到其上方有一个输人框,默认显示文字是http://google.com,我们将其换成 htps://www.baidu.com 测试一下,换完内容后单击 Render me! 按钮,开始渲染,结果如下图所示。

渲染结果中包含渲染截图、HAR 加载统计数据和网页的源代码。Splash 染了整个网页,包括CSS、JavaScript 的加载等,最终呈现的页面和在浏览器中看到的完全一致。那么,这个过程由什么控制呢?我们返回首页,可以看到这样一段脚本:
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
这个脚本是用Lua语言写的。即使不懂Lua语言的语法,也能大致看懂脚本的表面意思,首先调用go方法加载页面,然后调用 wait 方法等待了一定时间,最后返回了页面的源代码、截图和 HAR 信息。
至此,我们大体了解了 Splash 是通过 Lua 脚本控制页面的加载过程,加载过程完全模拟浏览器最后可返回各种格式的结果,如网页源码和截图等。
接下来,我们就了解一下 Lua 脚本的写法以及相关 API的用法。
Splash Lua 脚本
Splash 能够通过 Lua 脚本执行一系列渲染操作,因此我们可以用它模拟 Chrome、PhantomJS,先了解一下 Splash Lua 脚本的入口和执行方式。
- 入口及返回值
来看一个基本实例:
function main(splash, args)splash:go("http://www.baidu.com")splash:wait(0.5)local title = splash:evaljs("document.title")return {title=title}
end
将这段代码粘贴到上图中的代码编辑区域,然后单击 Render me! 按钮,返回结果如下图所示。

可以看到,渲染结果中包含网页的标题。这里我们通过evaljs 方法传人了 JavaScript 脚本,而document.title 返回的就是网页的标题,evaljs 方法执行完毕后将标题赋值给 title 变量,随后将其返回。
注意,我们在这里定义的方法叫 main。这个名称是固定的,Splash会默认调用这个方法。main方法的返回值既可以是字典形式,也可以是字符串形式,最后都会转化为Splash的 HTTP 响应,例如:
function main(splash)return {hello="world!"}
end
返回的是字典形式的内容。下面的代码:
function main(splash)return 'hello'
end
返回的是字符串形式的内容。
- 异步处理
Splash 支持异步处理,但是并没有显式地指明回调方法,其回调的跳转是在内部完成的。示例如下:
function main(splash, args)local example_urls = {"www.baidu.com","www.taobao.com","www.zhihu.com"}local urls = args.urls or example_urlslocal results = {}for index,url in ipairs(urls) dolocal ok,reason = splash:go("http://" .. url)if ok thensplash:wait(2)results[url] = splash:png()endendreturn results
end
运行这段代码后的返回结果是代码中3个网站的页面截图,如下图所示。

代码中调用的 wait 方法类似于 Python 中的 sleep 方法,参数是等待的秒数。当 Splash 执行到此方法时,会转而处理其他任务,在等待参数指定的时间后再回来继续处理。
这里值得注意的是,Lua 脚本中的字符串拼接和 Python 中不同,它使用的是“…”操作符,而不是66リ如果有必要,可以简单了解一下 Lua 脚本的语法,详见 http:/www.runoob.com/ua/lua-basic-syntax.html.另外,这里设置了加载页面时的异常检测。80方法会返回加载页面的结果状态,如果返回的状态码是 4xx或 5xx,那么 ok 变量为空,就不会返回加载后的图片。
splash 对象的属性
能够注意到,前面例子中 main方法的第一个参数是 splash,这个对象非常重要,类似于Selenium中的 webDriver 对象,我们可以调用它的一些属性和方法来控制加载过程。接下来,先看 splash 的属性。
- args 属性
该属性用于获取页面加载时配置的参数,例如请求 URL。对于 GET请求,args 属性还可以用于获取 GET请求的参数;对于POST请求,args属性还可以用于获取表单提交的数据。此外,Splash 支持将 main 方法的第二个参数直接设置为 args,例如:
function main(splash, args)local url= args.url
end
这里的第二个参数 args 就相当于 splash.args 属性,以上代码等价于:
function main(splash)local url=splash.args.url
end
- js_enabled 属性
这个属性是 Splash 执行 JavaScript 代码的开关,将其设置为 true 或 false 可以控制是否执行JavaScript 代码,默认取 true。例如:
function main(splash, args)splash:go("https://www.baidu.com" )splash.js enabled=falselocal title = splash:evaljs("document.title")return {title=title}
end
这里我们将 is enabled 设置为 false,代表禁止执行 JavaScript代码,然后重新调用 evaljs 方法执行了 JavaScript 代码,此时运行这段代码,就会抛出异常:

不过,我们一般不设置此属性,默认开启。
- resource_timeout 属性
此属性用于设置页面加载的超时时间,单位是秒。如果设置为0或nil(类似Python 中的None).
代表不检测超时。示例如下:
function main(splash)splash.resource_timeout = 0.1assert(splash:go('https://www.taobao.com'))return splash:png()
end
这里将超时时间设置为了 0.1秒。意味着如果在0.1秒内没有得到响应,就抛出异常:

此属性适合在页面加载速度较慢的情况下设置。如果超过某个时间后页面依然无响应,则直接抛出异常并忽略。
- images_enabled 属性
此属性用于设置是否加载图片,默认是加载。禁用该属性可以节省网络流量并提高页面的加载速度,但是需要注意,这样可能会影响 JavaScript 渲染。因为禁用该属性之后,它的外层 DOM 节点的高度会受影响,进而影响 DOM 节点的位置。当JavaScript 对图片节点执行操作时,就会受到影响。
另外有一点值得注意,Spiash会使用缓存。意味着即使禁用images_enabled属性,一开始加载出来的网页图片也会在重新加载页面后显示出来,这种情况下直接重启Splash 即可。
禁用 images_enabled 属性的示例如下:
function main(splash, args) splash.images_enabled=falseassert(splash:go('https://www.jd.com'))return{png=splash:png()}
end
这样返回的页面截图不会带有任何图片,加载速度也会快很多。
- plugins_enabled 属性
此属性用于控制是否开启浏览器插件(如 Flash 插件 ),默认取 false,表示不开启。可以使用如下代码开启/关闭 plugins_enabled:
splash.plugins enabled = true/false
- scroll_position属性
此属性可以控制页面上下滚动或左右滚动,是一个比较常用的属性。示例如下:
function main(splash, args)assert(splash:go('https://www.taobao.com'))splash.scroll_position={y=400}return {png=splash:png()}
end
这样可以控制页面向下滚动 400 像素值,运行结果如下图所示。

如果要让页面左右滚动,可以传入x参数,代码如下:
splash.scroll_position={x=100,y=200}
splash 对象的方法
除了前面介绍的属性,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_method:请求方法,是可选参数,默认为GET,同时支持 POST。口 body:http_method为POST时的表单数据,使用的Content-type为application/json,是可选参数,默认为空。
- formdata:http_method 为 POST 时的表单数据,使用的 Content-type 为 application/x-www-form-urlencoded,是可选参数,默认为空。
该方法的返回值是ok变量和 reason 变量的组合,如果 ok为空,代表页面加载出现了错误,reason中包含错误的原因,否则代表页面加载成功。示例如下:
function main(splash, args)local ok, reason = splash:go{"http://www.httpbin.org/post", http_method="PosT", body="name-Germey"}if ok thenreturn splash:html()end
end
这里我们模拟了一个POST请求,并传人了表单数据,如果页面加载成功,就返回页面的源代码。
运行结果如下:

可以看到成功实现了POST请求并发送了表单数据。
- wait方法
此方法用于控制页面等待时间,其用法如下:
ok, reason=splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}
对其中各参数的说明如下。
- time:等待的时间,单位为秒。
- cancel_on_redirect:如果发生了重定向就停止等待,并返回重定向结果,是可选参数,默认为 false。
- cancel_on_error:如果页面加载错误就停止等待,是可选参数,默认为 false。
其返回值同样是 ok 变量和 reason 变量的组合。
我们用一个实例感受一下:
function main(splash)splash:go("https://www.taobao.com")splash:wait(2)return {html=splash:html()}
end
执行如上代码,可以访问淘宝页面并等待2秒,随后返回页面源代码。
- 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
这段代码的运行结果如下:

这里我们先声明了一个 JavaScript定义的方法 get div_count,然后在页面加载成功后调用此方法计算出了页面中 div 节点的个数。
关于从 JavaScript方法转换到Lua脚本的更多细节,可以参考官方文档:https://splash.readthedocs.
io/en/stable/scripting-ref.html#splash-jsfunc。
- evaljs 方法
此方法用于执行 JavaScript 代码并返回最后一条 JavaScript 语句的返回结果,其用法如下:
result=splash:evaljs(js)
例如,可以用下面的代码获取页面标题:
local title =splash:evaljs("document.title")
- runjs 方法
此方法用于执行JavaScript代码,它的功能与evalis方法类似,但更偏向于执行某些动作或声明某些方法。例如:
function main(splash, args)splash:go("https://www.baidu.com")splash:runjs("foo =function(){return 'bar'}")local result=splash:evaljs("foo()")return result
end
这里我们先用 runjs 方法声明了一个 JavaScript 方法 foo,然后通过 evaljs 方法调用 foo 方法得到的结果。
运行结果如下:

可以看到,这里我们成功模拟了发送POST请求,并发送了表单数据。
- html方法
此方法用于获取页面的源代码,是一个非常简单且常用的方法,示例如下:
function main(splash, args)splash:go("https://www.httpbin.org/get")return splash:html()
end
运行结果如下:

- png 方法
此方法用于获取 PNG 格式的页面截图,示例如下:
function main(splash, args)splash:go("https://www.taobao.com")return splash:png()
end
- jpeg 方法
此方法用于获取 JPEG 格式的页面截图,示例如下:
function main(splash, args)splash:go("https://www.taobao.com")return splash:jpeg()
end
- har 方法
此方法用于获取页面加载过程的描述信息,示例如下:
function main(splash, args)splash:go("https://www.baidu.com")return splash:har()
end
运行结果如下图所示:

这张图里显示了百度页面加载过程中的每个请求记录的详情。
- url方法
此方法用于获取当前正在访问的URL,示例如下:
function main(splash, args)splash:go("https://www.baidu.com")return splash:url()
end
运行结果如下:

- set_user_agent 方法
此方法用于设置浏览器的 User-Agent,示例如下:
function main(splash)splash:set_user_agent('Splash')splash:go("http://www.httpbin.org/get")return splash:html()
end
这里我们将浏览器的 User-Agent 属性设置为了 Splash,运行结果如下:

可以看到,我们设置的 User-gent 属性值生效了。
- select 方法
该方法用于选中符合条件的第一个节点,如果有多个节点符合条件,则只返回一个,其参数是CSS选择器。示例如下:
function main(splash)splash:go("https://www.baidu.com/")input =splash:select("#kw")input:send_text('Splash')splash:wait(3)return splash:png()
end
这里我们首先访问百度官网,然后用select 方法选中搜索框,随后调用 send_text 方法填写了文本,最后返回网页截图。运行结果如下图所示。

可以看到,我们成功填写了输入框。
- select_all方法
此方法用于选中所有符合条件的节点,其参数是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)doresults[index]= text.node.innerHTMLendreturn treat.as_array(results)
end

可以发现,我们成功获取了10个节点的正文内容。
- mouse_click方法
此方法用于模拟鼠标的点击操作,参数为坐标值x、y。我们可以直接选中某个节点直接调用此方法,示例如下:
function main(splash)splash:go("https://www.baidu.com/")input = splash:select("#kw")input:send_text('Splash')splash:wait(3)submit=splash:select('#su')submit:mouse_click()splash:wait(5)return splash:png()
end
这里我们首先选中页面的输入框,向其中输人文本 Splash,然后选中提交按钮,调用mouse click方法提交査询,之后等待5秒,就会返回页面截图,如下图所示。

可以看到,我们成功获取了查询后的页面内容,模拟了百度的搜索操作。
至此,splash对象的常用方法介绍完毕,还有一些方法这里不一一介绍了,更加详细和权威的说明可以参见官方文档 https://splash.readthedocs.io/en/stable/scripting-ref.html,此页面介绍了splash 对象的所有方法。另外,还有针对页面元素的方法,见官方文档 https://splash.readthedocs.io/en/stable/scriptingelement-object.html.
调用 Splash 提供的 API
前面我们介绍了 SplashLua脚本的用法,但这些脚本是在 Splash 页面里测试运行的,如何才能利用 Splash 渲染页面?Splash 怎样才能和 Python 程序结合使用并爬取 JavaScript 渲染的页面?
其实,Splash 给我们提供了一些 HTTP API,我们只需要请求这些 API 并传递相应的参数即可获取页面渲染后的结果,下面我们学习这些 API。
- render.html
此 AP 用于获取 JavaScript 渲染的页面的 HTML代码,API地址是 Splash 的运行地址加上此 API的名称,例如 http://ocalhost:8050/renderhtml,我们可以用 curl 工具测试一下:
curl http://localhost:8050/render.html?url=https://www.baidu.com
我们给此 API传递了一个 ur1 参数,以指定渲染的 URL,返回结果即为页面渲染后的源代码。
import requestsurl='http://localhost:8050/render.html?url=https://www.baidu.com'
response =requests.get(url)
print(response.text)
这样就可以成功输出百度页面渲染后的源代码了。
此 API还有其他参数,例如 wait,用来指定等待秒数。如果要确保页面完全加载出来,就可以设置此参数,例如:
import requestsurl='http://localhost:8050/render.html?url=https://www.baidu.com&wait=5'
response =requests.get(url)
print(response.text)
增加等待时间后,得到响应的时间会相应变长,如这里我们等待大约5秒钟才能获取 JavaScript 渲染后的淘宝页面源代码。
另外,此API还支持代理设置、图片加载设置、请求头设置和请求方法设置,具体的用法可以参见官方文档 https://splash.readthedocs.io/en/stable/api.html#render-html。
- render.png
此 API用于获取页面截图,其参数比 render.html 要多几个,例如 width 和 height 用来控制截图的宽和高,返回值是 PNG 格式图片的二进制数据。示例如下:
curl http://localhost:8050/render.png?url=https://ww.taobao.com&wait-5&width=1000&height=700
这里我们通过设置 width 和 height 参数,将页面截图的大小缩放为 1000x700 像素。如果用 Python 实现,可以将返回的二进制数据保存为 PNG 格式的图片,代码如下:
import requestsurl = ('http://localhost: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)
得到的图片如下图所示。

这样我们就成功获取了京东首页渲染完成后的页面截图,详细的参数设置可以参考官网文档https://splash.readthedocs.io/en/stable/api.html#render-png.
- render.jpeg
此 API和 render.png 类似,不过它返回的是 JPEG 格式图片的二进制数据
另外,此API比 render.png 多一个参数quality,该参数可以设置图片质量。
- render.har
此 API用于获取页面加载的 HAR 数据,示例如下:
curl http://localhost:8050/render.har?url=https://www.jd.com&wait=5
运行结果非常多,是一个JSON格式的数据,里面包含页面加载过程中的 HAR 数据。
- render.json
此 API 包含前面介绍的所有 render 相关的 API的功能,返回值是 JSON 格式的数据,示例如下:
curl http://localhost:8050/render.json?url=https://www.httpbin.org
这里返回了 JSON 格式的请求数据。
我们可以通过传入不同的参数控制返回结果。例如,传入html=1,返回结果会增加页面源代码;传人 png=1,返回结果会增加 PNG格式的页面截图;传人 har=1,返回结果会增加页面的 HAR数据。例如:
curl http://localhost:8050/render.json?url=https://www.httpbin.org&html=1&har=1
这样返回的结果中便会包含页面源代码和 HAR 数据。
此外,还有其他参数可以设置,可以参考官方文档 https://splash.readthedocs.io/en/stable/api.html#render-json.
- execute
此 API才是最为强大的API。之前介绍了很多关于 SplashLua 脚本的操作,用此API即可实现与Lua 脚本的对接。
要爬取一般的 JavaScript 渲染页面,使用前面的 render.html 和 render.png 等 API 就足够了,但如果要实现一些交互操作,这些API还是心有余而力不足,就需要使用execute 了。
先实现一个最简单的脚本,直接返回数据:
function main(splash)return 'hello'
end
然后将此脚本转化为 URL编码后的字符串,拼接到execute后面,示例如下:
curl http://localhost:8050/execute?lua_source=function+main%28splash%29%0D%0A++return+%27he11o%27%0D%0Aend
运行结果如下:
hello
这里我们通过 lua_source 参数传递了转码后的 Lua 脚本,通过 execute 获取了脚本最终的执行结果。我们更加关心的是如何用 Python 实现上述过程,如果用 Python 实现,那么代码如下:
import requestsfrom urllib.parse import quotelua = '''
function main(splash)return 'hello'
end
'''url = 'http://localhost:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
print(response.text)
运行结果如下:
hello
这里我们用 Python 中的三引号将Lua脚本括了起来,然后用 urllib.parse模块里的 quote方法对脚本进行 URL转码,之后构造了请求 URL,并将其作为 lua_source 参数传递,这样运行结果就会显示Lua 脚本执行后的结果。
我们再通过实例看一下:
import requestsfrom urllib.parse import quotelua = '''
function main(splash)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://localhost:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
print(response.text)
运行结果如下:
{"html": "{\n \"args\": {}, \n \"headers\": {\n \"Accept-Encoding\": \"gzip, deflate\", \n \"Accept-Language\": \"en,*\", \n \"Host\": \"www.httpbin.org\", \n \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/10.0 Safari/602.1\", \n \"X-Amzn-Trace-Id\": \"Root=1-678293a3-209dd02a23aa508c59709099\"\n }, \n \"origin\": \"111.19.92.180\", \n \"url\": \"http://www.httpbin.org/get\"\n}\n", "url": "http://www.httpbin.org/get", "status": 200}
可以看到,返回结果是 JSON 形式的,我们成功获取了请求 URL、状态码和页面源代码。如此一来,之前所讲的 Lua 脚本就都可以用此方式与 Python 对接了,所有网页的动态渲染、模拟点击、表单提交、页面滑动、延时等待后的结果均可以自由控制获取细节,获取页面源代码和截图也都不在话下。
到现在为止,我们可以利用 Python 和 Splash 爬取 JavaScript渲染的页面了。除了 Selenium,Splash同样可以实现非常强大的渲染功能,同时它不需要浏览器便可渲染,使用起来非常方便。
负载均衡配置
用 Splash 爬取页面时,如果爬取的数据量非常大,任务非常多,那么只用一个 Splash 服务就会使压力非常大,此时可以考虑搭建一个负载均衡器把压力分散到多个服务器上,相当于多台机器、多个服务共同参与任务的处理,可以减小单个Splash 服务的压力。
由于篇幅原因,请移步 https://setup.scrape.center/splash-loadbalance 查看具体的配置方法。
总结
本篇博客中,我们全面地了解了 Splash 的基本用法。有了 Splash,可以将 JavaScript 动态渲染的操作完全托管到一个服务器上,爬虫爬取的时候不需要再依赖 Selenium 等库,整个业务逻辑会更加轻量级。
相关文章:
JavaScript动态渲染页面爬取之Splash
Splash是一个 JavaScript渲染服务,是一个含有 HTTP API的轻量级浏览器,它还对接了 Python 中的 Twisted 库和 OT库。利用它,同样可以爬取动态渲染的页面。 功能介绍 利用 Splash,可以实现如下功能: 异步处理多个网页的渲染过程:获取渲染后…...
慧集通(DataLinkX)iPaaS集成平台-系统管理之UI库管理、流程模板
UI库管理 UI库管理分为平台级和自建两种,其中平台级就是慧集通平台自己内置的一些ui库所有客户均可调用,自建则是平台支持使用者自己根据规则自己新增对应的UI库。具体界面如下: 自建UI库新增界面: 注:平台级UI库不支…...
OpenCV相机标定与3D重建(59)用于立体相机标定的函数stereoCalibrate()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 标定立体相机设置。此函数找到两个相机各自的内参以及两个相机之间的外参。 cv::stereoCalibrate 是 OpenCV 中用于立体相机标定的函数。它通过一…...
摄像头模块在狩猎相机中的应用
摄像头模块是狩猎相机的核心组件,在狩猎相机中发挥着关键作用,以下是其主要应用: 图像与视频拍摄 高清成像:高像素的摄像头模块可确保狩猎相机拍摄出清晰的图像和视频,能够捕捉到动物的毛发纹理、行为细节及周围环境的…...
ruoyi-cloud docker启动微服务无法连接nacos,Client not connected, current status:STARTING
ruoyi-cloud docker启动微服务无法连接nacos,Client not connected, current status:STARTING 场景 当使用sh deploy.sh base来安装mysql、redis、nacos环境后,紧接着使用sh deploy.sh modules安装微服务模块,会发现微服务无法连接nacos的情…...
代码随想录算法训练营第三十四天-动态规划-63. 不同路径II
本题与上一题区别不大但由于存在障碍格,导致在计算路径值时,要多考虑一些情况 比如,障碍格在开始与结束位置时,路径直接返回0障碍格在初始的首行与首列时,设置初始值要不同在计算dp值时,要先判断当前格是不…...
在一个sql select中作多个sum并分组
有表如下; 单独的对某一个列作sum并分组,结果如下; 对于表的第7、8行,num1都有值,num2都是null,对num2列作sum、按id分组,结果在id为4的行会显示一个null; 同时对2个列作sum&#x…...
家用电路频繁跳闸的原因及解决方法!
家庭电路跳闸是一个常见的用电故障,正确理解跳闸原因并采取恰当的处理方法,不仅能够及时恢复供电,更能预防潜在的安全隐患。 一、问题分析 断路器跳闸通常是电路保护装置在发现异常时的自动保护行为,主要出现以下几种情况…...
我的年度总结
这一年的人生起伏:从曙光到低谷再到新的曙光 其实本来没打算做年度总结的,无聊打开了帅帅的视频,结合自己最近经历的,打算简单聊下。因为原本打算做的内容会是一篇比较丧、低能量者的呻吟。 实习生与创业公司的零到一 第一段工…...
ASP.NET Core 多环境配置
一、开篇明义:多环境配置的重要性 在ASP.NET Core 开发的广袤天地中,多环境配置堪称保障应用稳定运行的中流砥柱。想象一下,我们精心打造的应用,要在开发、测试、预发布和生产等截然不同的环境中穿梭自如。每个环境都如同一个独特…...
docker 安装mongodb
1、先获取mongodb镜像 docker pull mongo:4.2 2、镜像拉取完成后,运行mongodb容器 docker run \ -d \ --name mongo \ --restartalways \ --privilegedtrue \ -p 27017:27017 \ -v /home//mongodb/data:/data/db \ mongo:4.2 --auth 3、mongodb服务配置 如上图&…...
完整地实现了推荐系统的构建、实验和评估过程,为不同推荐算法在同一数据集上的性能比较提供了可重复实验的框架
{"cells": [{"cell_type": "markdown","metadata": {},"source": ["# 基于用户的协同过滤算法"]},{"cell_type": "code","execution_count": 1,"metadata": {},"ou…...
DRV8311三相PWM无刷直流电机驱动器
1 特性 • 三相 PWM 电机驱动器 – 三相无刷直流电机 • 3V 至 20V 工作电压 – 24V 绝对最大电压 • 高输出电流能力 – 5A 峰值电流驱动能力 • 低导通状态电阻 MOSFET – TA 25C 时,RDS(ON) (HS LS) 为210mΩ(典型值) • 低功耗睡眠模式…...
Mysql--运维篇--备份和恢复(逻辑备份,mysqldump,物理备份,热备份,温备份,冷备份,二进制文件备份和恢复等)
MySQL 提供了多种备份方式,每种方式适用于不同的场景和需求。根据备份的粒度、速度、恢复时间和对数据库的影响,可以选择合适的备份策略。主要备份方式有三大类:逻辑备份(mysqldump),物理备份和二进制文件备…...
机器学习-归一化
文章目录 一. 归一化二. 归一化的常见方法1. 最小-最大归一化 (Min-Max Normalization)2. Z-Score 归一化(标准化)3. MaxAbs 归一化 三. 归一化的选择四. 为什么要进行归一化1. 消除量纲差异2. 提高模型训练速度3. 增强模型的稳定性4. 保证正则化项的有效…...
Linux 串口检查状态的实用方法
在 Linux 系统中,串口通信是非常常见的操作,尤其在嵌入式系统、工业设备以及其他需要串行通信的场景中。为了确保串口设备的正常工作,检查串口的连接状态和配置信息是非常重要的。本篇文章将介绍如何在 Linux 上检查串口的连接状态࿰…...
Qt的核心机制概述
Qt的核心机制概述 1. 元对象系统(The Meta-Object System) 基本概念:元对象系统是Qt的核心机制之一,它通过moc(Meta-Object Compiler)工具为继承自QObject的类生成额外的代码,从而扩展了C语言…...
微调神经机器翻译模型全流程
MBART: Multilingual Denoising Pre-training for Neural Machine Translation 模型下载 mBART 是一个基于序列到序列的去噪自编码器,使用 BART 目标在多种语言的大规模单语语料库上进行预训练。mBART 是首批通过去噪完整文本在多种语言上预训练序列到序列模型的方…...
Cesium加载地形
Cesium的地形来源大致可以分为两种,一种是由Cesium官方提供的数据源,一种是第三方的数据源,官方源依赖于Cesium Assets,如果设置了AccessToken后,就可以直接使用Cesium的地形静态构造方法来获取数据源CesiumTerrainPro…...
gitlab runner正常连接 提示 作业挂起中,等待进入队列 解决办法
方案1 作业挂起中,等待进入队列 重启gitlab-runner gitlab-runner stop gitlab-runner start gitlab-runner run方案2 启动 gitlab-runner 服务 gitlab-runner start成功启动如下 [rootdocserver home]# gitlab-runner start Runtime platform …...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
计算机系统结构复习-名词解释2
1.定向:在某条指令产生计算结果之前,其他指令并不真正立即需要该计算结果,如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方,那么就可以避免停顿。 2.多级存储层次:由若干个采用不同实现技术的存储…...
