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安装
  1. 去docker官网下载,但请一定要注意你Windows笔记本电脑版本一定要和docker匹配,否则会报错:
    在这里插入图片描述
  2. 查看自己windows版本
    检查 Windows 版本:按 Win + R 键,输入 winver,然后点击“确定”。这将显示一个窗口,其中包含您当前使用的 Windows 版本信息。

在这里插入图片描述

  1. 官网找一个合适的版本,一般历史版本可能官网不好找,点击这里找个适合的版本 下载。

  2. 安装包下载之后直接双击安装即可,不过可能会报错:
    在这里插入图片描述

  3. 去给出的网址下载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 等库,整个业务逻辑会更加轻量级。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/1618.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP详解——HTTP基础

HTTP 基本概念 HTTP 是超文本传输协议 (HyperText Transfer Protocol) 超文本传输协议(HyperText Transfer Protocol) HTTP 是一个在计算机世界里专门在 两点 之间 传输 文字、图片、音视频等 超文本 数据的 约定和规范 1. 协议 约定和规范 2. 传输 两点之间传输&#xf…

云服务信息安全管理体系认证,守护云端安全

在数据驱动的时代,云计算已成为企业业务的超级引擎,推动着企业飞速发展。然而,随着云计算的广泛应用,信息安全问题也日益凸显,如同暗流涌动下的礁石,时刻威胁着企业的航行安全。这时,云服务信息…

nacos环境搭建以及SpringCloudAlibaba脚手架启动环境映射开发程序

1:下载nacos 地址:https://github.com/alibaba/nacos/tags 2:选择server的zip包下载 3:启动mysql服务,新建数据库:nacos_yh 4:解压下载的nacos_server 进入conf目录 5:mysql运行sql脚本变得到下面的表 6&a…

stable diffusion 量化学习笔记

文章目录 一、一些tensorRT背景及使用介绍1)深度学习介绍2)TensorRT优化策略介绍3)TensorRT基础使用流程4)dynamic shape 模式5)TensorRT模型转换 二、TensorRT转onnx模型1)onnx介绍2)背景知识&…

设计模式 行为型 访问者模式(Visitor Pattern)与 常见技术框架应用 解析

访问者模式(Visitor Pattern)是一种行为设计模式,它允许你在不改变元素类的前提下定义作用于这些元素的新操作。这种模式将算法与对象结构分离,使得可以独立地变化那些保存在复杂对象结构中的元素的操作。 假设我们有一个复杂的对…

C++中引用参数与指针参数的区别与联系详解

在C++中,函数参数可以通过值传递、引用传递和指针传递。虽然指针传递在C和C++中都非常常见,但C++引入了引用类型,使得引用传递变得更加直接和易用。本文将详细介绍函数中引用参数和指针参数的区别与联系,并通过C++语言代码示例加以说明。 一、基本概念 值传递(Pass by Val…

初识JVM HotSopt 的发展历程

目录 导学 目前企业对程序员的基本要求 面向的对象 实战 学习目标 JVM 是什么 JVM 的三大核心功能 各大 JVM look 看一下虚拟机 HotSopt 的发展历程 总结 导学 目前企业对程序员的基本要求 面向的对象 实战 学习目标 JVM 是什么 JVM 的三大核心功能 即时编译 主要是…

html中鼠标位置信息

pageX:鼠标距离页面的最左边的距离,包括滚动条的长度。clientX:鼠标距离浏览器视口的左距离,不包括滚动条。offsetX:鼠标到事件源左边的距离。movementX:鼠标这次触发的事件的位置相对于上一次触发事件的位…

RabbitMQ 高可用方案:原理、构建与运维全解析

文章目录 前言:1 集群方案的原理2 RabbitMQ高可用集群相关概念2.1 设计集群的目的2.2 集群配置方式2.3 节点类型 3 集群架构3.1 为什么使用集群3.2 集群的特点3.3 集群异常处理3.4 普通集群模式3.5 镜像集群模式 前言: 在实际生产中,RabbitM…

【容器逃逸实践】挂载/dev方法

0、前置知识 怎么在容器里面执行命令, 有几种方法 # 不进入容器,创建并启动一个新的容器 $ docker run -itd --name ubuntu-test ubuntu /bin/bash # 进入容器,创建并启动一个新的容器 $ docker run -itd --name ubuntu-test ubuntu /bin…

linux: 文本编辑器vim

文本编辑器 vi的工作模式 (vim和vi一致) 进入vim的方法 方法一:输入 vim 文件名 此时左下角有 "文件名" 文件行数,字符数量 方法一: 输入 vim 新文件名 此时新建了一个文件并进入vim,左下角有 "文件名"[New File] 灰色的长方形就是光标,输入文字,左下…

Python爬虫-汽车之家各车系周销量榜数据

前言 本文是该专栏的第43篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏之前,笔者在文章《Python爬虫-汽车之家各车系月销量榜数据》中,有详细介绍,如何爬取“各车系车型的月销量榜单数据”的方法以及完整代码教学教程。 而本文,笔者同样以汽车之家平台为例,…

Python----Python高级(函数基础,形参和实参,参数传递,全局变量和局部变量,匿名函数,递归函数,eval()函数,LEGB规则)

一、函数基础 1.1、函数的用法和底层分析 函数是可重用的程序代码块。 函数的作用,不仅可以实现代码的复用,更能实现代码的一致性。一致性指的是,只要修改函数的代码,则所有调用该函数的地方都能得到体现。 在编写函数时&#xf…

欧拉路径算法

欧拉图: 对于应该连通图G,有: 1欧拉路径:一条路径,它能够不重复地遍历完所有的边,这个性质很像不重复地一笔画完所有边,所以有些涉及到欧拉路径的问题叫做一笔画问题。 2欧拉回路&#xff1a…

后端技术选型 sa-token校验学习 下 结合项目学习 后端鉴权

目录 后端注册拦截器 实现对 WebMvcConfigurer 接口的类实现 静态变量 方法重写 注册 Spring Framework拦截器 Sa-Token中SaServletFilter拦截器 思考 为什么使用两个拦截器 1. Spring Framework 拦截器 2. SaServletFilter 为什么要注册两个拦截器? 总结 …

Angular-生命周期及钩子函数

什么是生命周期 Angular 创建和渲染组件及其子组件,当它们绑定的属性发生变化时检查它们,并在从 DOM 中移除它之前销毁它们。生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。当 Angular 使用构造函数新建一个组件或…

Microsoft

Microsoft Word目录1.目录编号与文字的间距设置2. 目录编号缩进设置 Excel函数MID(提取字符)CONCAT(组合字符串)EXACT(比较字符串) PowerPointwindows 11 恢复右键传统菜单 Word 目录 1.目录编号与文字的…

MAC AndroidStudio模拟器无网络

先确认PC端是正常访问网络的; 模拟器端修改Wifi设置:设置 - 网络和互联网 - WALN设置 按照上图修改; IP设置:从DHCP修改为静态,IP地址:10.0.2.16 ,网关:10.0.2.2 , DNS…

Android 对接口的封装使用

前言 本篇文章主要是记录Android代码 对java 接口的封装和使用方法,比较基础,记录一下,阅读本篇文章前,请移步 java基础系列(九) 接口和抽象类 这篇文章。 接口理解 从设计角度: 设计方面的区别 抽象类是对一种事物的抽象&#…

Qiskit快速编程探索(进阶篇)

五、量子电路模拟:探索量子世界的虚拟实验室 5.1 Aer模拟器:强大的模拟引擎 在量子计算的探索旅程中,Aer模拟器作为Qiskit的核心组件之一,宛如一座功能强大的虚拟实验室,为开发者提供了在经典计算机上模拟量子电路运行的卓越能力。它打破了硬件条件的限制,使得研究者无…