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_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

运行这段代码后的返回结果是代码中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=false
	local 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.1
	assert(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=false
	assert(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 then
  	return 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)do
    results[index]= text.node.innerHTML
  end
  return 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 requests

url='http://localhost:8050/render.html?url=https://www.baidu.com'
response =requests.get(url)
print(response.text)

这样就可以成功输出百度页面渲染后的源代码了。
此 API还有其他参数,例如 wait,用来指定等待秒数。如果要确保页面完全加载出来,就可以设置此参数,例如:

import requests

url='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 requests

url = ('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 requests

from urllib.parse import quote

lua = '''
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 requests

from urllib.parse import quote

lua = '''
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 等库,整个业务逻辑会更加轻量级。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Thrustmaster Hotas Warthog飞行操作杆开发

目录 0 摘 要 :简单说一下这篇文章在搞啥 1 背 景 :什么需求以及对开发的背景调查 2 环境配置 :具体需要什么环境,对软件层面的需求 3 硬件测试 :测试遥感器…

算法-查找数组对角线上最大的质数

力扣题目:2614. 对角线上的质数 - 力扣(LeetCode) 给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数,返回 0 。 注意: 如果某个整数大于…

电梯系统的UML文档02

现在我们来回答用UML 设计电梯系统的实践中遇到的问题:“UML 是一种适合于实时系统的建模语言吗?”我们发现基于上段提到的特征,UML 是适合的但有不足。用UML 设计实时系统有以下问题: •特定硬件及它们特征的定义。 •在对象、任务和硬件层…

mysql set age=‘0‘ 和 set age=0的区别?

select case when(t1.business_transfer‘source’)then 0 else t1.settlement_tyy_cash_amount end as tyy from t_settlement_waybill t1 where waybill_sn in (‘2025010700001’); select case when(t1.business_transfer‘source’)then (t1.settlement_tyy_cash_amount‘…

利用Java爬虫按图搜索1688商品(拍立淘)的实践指南

在当今数字化时代,网购已成为人们生活中不可或缺的一部分。而1688作为国内领先的B2B电商平台,汇聚了海量的商品资源。然而,在面对众多商品时,传统的文字搜索方式有时难以满足我们的需求。比如,当我们看到一件心仪的商品…

达梦8-DMSQL程序设计学习笔记1-DMSQL程序简介

1、DMSQL程序简介 DMSQL程序是达梦数据库对标准SQL语言的扩展,是一种过程化SQL语言。在DMSQL程序中,包括一整套数据类型、条件结构、循环结构和异常处理结构等,DMSQL程序中可以执行SQL语句,SQL语句中也可以使用DMSQL函数。 DMSQ…

使用 WPF 和 C# 将纹理应用于三角形

此示例展示了如何将纹理应用于三角形,以使场景比覆盖纯色的场景更逼真。以下是为三角形添加纹理的基本步骤。 创建一个MeshGeometry3D对象。像往常一样定义三角形的点和法线。通过向网格的TextureCoordinates集合添加值来设置三角形的纹理坐标。创建一个使用想要显示的纹理的 …

Git版本控制 - 创建使用Repository

Git版本控制 – 创建使用Repository Version Control with Git - Create and Use Repository By JacksonML 上文提到,Git是一种分布式版本控制系统。作为全球范围内广泛使用的工具,如何将项目分步骤运用到其中呢? 本文简要介绍如何用Git工…

WINFORM - DevExpress -> devexpress版--报表(report)

devexpress report模板 1.安装devexpress(DevExpress 总结【安装、案例】_caoyanchao1的博客-CSDN博客_devexpress) 2.新建vs项目且添加standarReportDesigner控件 涛神设计器注意 3.运行后步骤 点击New Report DetailReport 涛神设计器checkbox(3.复选框只认boolean类型的 b…

【Redis】初识Redis

目录 Redis简介 Redis在内存中存储数据 Redis数据库中的应用 Redis缓存中的应用 Redis消息中间件 尾言 Redis简介 如下是Redis官网中,对Redis的一段描述 在这段描述中,我们提取如下关键要点: Redis主要用于在内存中存储数据Redis可…

YOLOv9改进,YOLOv9自研检测头融合HAttention用于图像修复的混合注意力检测头

参考文章 完成本篇内容,首先完成这篇文章,并把代码添加到 YOLOv9 中: YOLOv9改进,YOLOv9引入HAttention注意机制用于图像修复的混合注意力转换器,CVPR2023,超分辨率重建 下文都是手把手教程,跟着操作即可添加成功 目录 参考文章🎓一、YOLOv9原始版本代码下载🍀🍀…

[读书日志]8051软核处理器设计实战(基于FPGA)第七篇:8051软核处理器的测试(verilog+C)

6. 8051软核处理器的验证和使用 为了充分测试8051的性能,我们需要测试每一条指令。在HELLO文件夹中存放了整个测试的C语言工程文件。主函数存放在指令被分为五大类,和上面一样。 打开后是这样的文件结构。HELLO.c是主文件,这是里面的代码&am…

occ的开发框架

occ的开发框架 1.Introduction This manual explains how to use the Open CASCADE Application Framework (OCAF). It provides basic documentation on using OCAF. 2.Purpose of OCAF OCAF (the Open CASCADE Application Framework) is an easy-to-use platform for ra…

python识别图片中指定颜色的图案并保存为图片

示例代码: def chuli(color):import cv2import numpy as np# 定义颜色名称到HSV阈值范围的映射color_thresholds {red: ([0, 100, 100], [10, 255, 255], [160, 100, 100], [180, 255, 255]),yellow: ([20, 100, 100], [30, 255, 255]),blue: ([90, 100, 100], [1…

《利用深度神经网络在广角小口径望远镜中实现天文目标的检测与分类》论文精读

摘要 大口径小口径望远镜被广泛应用于光学瞬态观测,对观测图像中的天文目标进行检测和分类是最重要也是最基础的步骤。本文提出了一种基于深度神经网络的天文目标检测与分类框架。该框架采用了Faster R-CNN的概念,以改进的Resnet-50为主干网络&#xff…

Redis数据结构服务器

Redis数据结构服务器 什么是Redis数据结构服务器 的概念和特点 是一个开源(BSD许可),内存中的数据结构存储服务器,可用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如字符串(strings&#xff09…

逻辑测试题

https://blog.csdn.net/qq_39081315/article/details/121393597 先生成一个点,每生成一个点判断距离,角度,满足加入存点的容器,直到容器大小为4。 随机生成点: 分区域:最大距离20,以20为正方形…

【UE5 C++课程系列笔记】27——多线程基础——ControlFlow插件的基本使用

目录 步骤 一、搭建基本同步框架 二、添加委托 三、添加蓝图互动框架 四、修改为异步框架 完整代码 通过一个游戏初始化流程的示例来介绍“ControlFlows”的基本使用。 步骤 一、搭建基本同步框架 1. 勾选“ControlFlows”插件 2. 新建一个空白C类,这里…

前端性能优化方面

页面加载过程 网页资源的加载通常需要以下基本步骤: 地址栏输入网页服务器地址 浏览器获取网页html文件 解析html文件中存在的js、css、图片等资源,通过网络线程加载 在特定时机执行js代码,可以在js中动态加载需要的静态资源 执行js里存在的f…

解锁“搭子小程序”开发新机遇,助力企业数字化转型

搭子作为一种新型的社交方式,逐渐进入到了年轻人的生活中,在日常旅游、学习、逛街等,年轻人都可以找到志同道合的“搭子”,提高生活的幸福指数。 随着搭子市场的发展,通过互联网寻找搭子已经成为了年轻人的必备方式。…