JavaScript动态渲染页面爬取——Splash的使用

JavaScript动态渲染页面爬取

JavaScript动态渲染得页面不止Ajax一种。例如,有些页面的分页部分由JavaScript生成,而非原始HTML代码,这其中并不包含Ajax请求。还有类似淘宝这种页面,即使是Ajax获取的数据,其Ajax接口中也含很多加密参数,使我们难以直接找出规律,也很难直接通过分析Ajax爬取数据。

为解决这些问题,可以直接模拟浏览器运行,然后爬取数据,这样就可以实现再浏览器中看到的内容是什么样,爬取的源码就是什么样------所见即所爬。无须去管网页内部的JavaScript使用什么算法渲染页面,也不用管网页后台的Ajax接口到底含有哪些参数。

Python提供了许多模拟浏览器运行的库,例如Selenium、Splash、Pyppetter、Playwright等,

可以实现所见即所爬,轻松爬取动态渲染页面。

Splash的使用

Splash是一个JavaScript渲染服务,是一个含有HTTP API的轻量级浏览器,它还对接了Python中的Twisted库和QT库。利用它,同样可以爬取动态渲染的页面。

1. 功能介绍

利用Splash,可以实现如下功能:

  • 异步处理多个网页的渲染过长;
  • 获取渲染后页面的源代码或截图;
  • 通过关闭图片渲染或者使用Adblock规则的方式加快页面渲染的速度;
  • 执行特定的JavaScript脚本;
  • 通过Lua脚本控制页面的渲染过程;
  • 获取页面渲染的详细过程并以HAR(HTTP Archive)的格式呈现出来。

接下来,一起了解Splash的具体用法。

2. 准备工作

请确保Splash已经正确安装好并可以在本地8050端口上正常运行。

3. 实例引入

首先,利用Splash提供的Web页面来测试其渲染过程。例如,在本机8050端口上运行Splash服务,然后打开http://localhost:8050/,即可看到Splash的Web页面,如图所示:

下面呈现的是一个渲染示例,可以看到其上方有一个输入框,默认显示文字是http://google.com,将其换成https://www.baidu.com测试一下,换完以后单击Render me!按钮,开始渲染,结果如下图所示:

渲染结果中包含渲染截图、HAR加载统计数据和网页的源代码。Splash渲染了整个网页,包括CSS、JavaScript的加载等,最终呈现的页面和在浏览器中看到的完全一致。

那么,这个过程由什么控制呢?我们返回首页,可以看到这样一段脚本:

lua 复制代码
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脚本控制页面的加载过程,加载过程完全模拟浏览器,最后可返回各种格式的结果,如网页源码和截图等。

4. Splash Lua脚本

用它模拟Chrome、PhantomJS。先了解一下Splash Lua脚本的入口和执行方式。

  • 入口及返回值

基本实例:

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响应,例如:

lua 复制代码
function main(splash)
	return {hello="world!"}
end

下面的代码:

lua 复制代码
function main(splash)
	return 'hello'
end

返回的是字符串形式的内容。

  • 异步处理

Splash支持异步处理,但是并没有显式地指明回调方法,其回调的跳转是在内部完成的,示例如下:

lua 复制代码
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中不同,它使用的是"..."操作符,而不是"+"。

5. Splash 对象的属性

能够注意到,前面例子中main方法的第一个参数是splash,这个对象非常重要,类似于Selenium中的WebDriver对象,我们可以调用它的一些属性和方法来控制加载过程。接下来,先看splash的属性。

  • args属性

该属性用于获取页面加载时配置的参数,例如请求URL。对于GET请求,args属性还可以用于获取GET请求的参数;对于POST请求,args属性还可以用于获取表单提交的数据。此外,Splash支持将main方法的第二个参数直接设置为args,例如:

lua 复制代码
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。例如:

lua 复制代码
function main(splash, args)
  splash:go("https://www.baidu.com")
  splash:js_enabled = false
  local title = splash:evaljs("document.title")
  return {title = title}
end

这里我们将js_enabled设置为false,代表禁止执行JavaScript代码,然后重新调用evaljs方法执行了JavaScript代码,此时运行这段代码,就会抛出异常:

lua 复制代码
Error occured
HTTP Error 400 (Bad Request)
Type: ScriptError -> LUA_INIT_ERROR
Error happened while executing Lua script

[string "function main(splash, args) ..."]:3: function arguments expected near '='

{
    "error": 400,
    "type": "ScriptError",
    "description": "Error happened while executing Lua script",
    "info": {
        "source": "[string \"function main(splash, args)\r...\"]",
        "line_number": 3,
        "error": "function arguments expected near '='",
        "type": "LUA_INIT_ERROR",
        "message": "[string \"function main(splash, args)\r...\"]:3: function arguments expected near '='"
    }
}

不过,我们一般不设置此属性,默认开启。

  • resource_timeout属性

此属性用于设置页面加载的超时时间,单位是秒。如果设置为0或nil(类似Python中的None),代表不检测超时。示例如下:

lua 复制代码
function main(splash)
  splash.resource_timeout = 0.1
  assert(splash:go('https://www.taobao.com'))
  return splash:png()
end

这里将超时时间设置为0.1秒。意味着如果在0.1秒内没有得到响应,就抛出异常:

lua 复制代码
{
    "error": 400,
    "type": "ScriptError",
    "description": "Error happened while executing Lua script",
    "info": {
        "source": "[string \"function main(splash, args)\r...\"]",
        "line_number": 3,
        "error": "function arguments expected near '='",
        "type": "LUA_INIT_ERROR",
        "message": "[string \"function main(splash, args)\r...\"]:3: function arguments expected near '='"
    }
}

此属性适合在页面加载速度较慢的情况下设置。如果超过某个时间后页面依然无响应,则直接抛出异常并忽略。

  • images_enabled属性

此属性用于设置是否加载图片,默认是加载。禁用该属性可以节省网络流量并提高页面的加载速度,但是需要注意,这样可能会影响JavaScript渲染。因为禁用该属性之后,它的外层DOM节点的高度会受影响,进而影响DOM节点的位置。当JavaScript对图片节点执行操作时,就会受到影响。另外Splah会使用缓存。意味着即使禁用images_enabled属性,一开始加载出来的网页图片也会在重新加载页面后显示出来,这种情况下直接重启Splash即可。

禁用images_enabled属性的示例如下:

lua 复制代码
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。

lua 复制代码
splash.plugins_enabled = true/false
  • scroll_position属性

此属性可以控制页面上下滚动或左右滚动,是一个比较常用的属性。示例如下:

lua 复制代码
function main(splash, args)
	assert(splash:go('https://www.taobao.com'))
  splash:scroll_position = {y=400}
  return {png=splash.png()}
  
end

这样可以控制页面向下滚动400像素值,运行结果如下图所示:

6. splash对象的方法

  • go方法

该方法用于请求某个链接,可以模拟GET请求和POST请求,同时支持传入请求头、表单等数据,其用法如下:

lua 复制代码
ok, reason = splash:go{url, baseur=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中包含错误的原因,否则代表页面加载成功,示例如下:

lua 复制代码
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请求,并传入了表单数据,如果页面加载成功,就返回页面的源代码。运行结果如下:

lua 复制代码
<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,*", 
    "Content-Length": "11", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "www.httpbin.org", 
    "Origin": "null", 
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/10.0 Safari/602.1", 
    "X-Amzn-Trace-Id": "Root=1-6603880b-2cce147d34fa0209280234df"
  }, 
  "json": null, 
  "origin": "122.143.56.182", 
  "url": "http://www.httpbin.org/post"
}
</pre></body></html>

可以看到,成功实现了POST请求并发送了表单数据。

  • wait方法

此方法用于控制页面等待时间,其用法如下:

lua 复制代码
ok, reason = splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}

对其中各参数的说明如下。

  • time:等待的时间,单位为秒
  • cancel_on_redirect:如果发生了重定向就停止等待,并返回重定向结果,是可选参数,默认为false。
  • cancel_on_error:如果页面加载错误就停止等待,是可选参数,默认为false。

其返回值同样是ok变量和reason变量的组合。

我们用一个实例感受一下:

lua 复制代码
function main(splash)
  splash:go('https://www.taobao.com')
  splash:wait(2)
  return {html=splash:html()}
end

执行如上代码,可以访问淘宝页面并等待2秒,随后返回页面源代码。

  • jsfunc方法

此方法用于直接调用JavaScript定义的方法,但是需要用双中括号把调用的方法包起来,相当于实现了从JavaScript方法到Lua脚本的转换。示例如下:

lua 复制代码
function main(splash)
  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

这段代码的运行结果如下:

lua 复制代码
Splash Response: "There are 148 DIVs"
  • evaljs方法

此方法用于执行JavaScript代码并返回最后一条JavaScript语句的返回结果,其用法如下:

lua 复制代码
result = splash:evaljs(js)

例如,可以用下面的代码获取页面标题:
local title = splash:evaljs("document.title")
  • runjs方法

此方法用于执行JavaScript代码,它的功能与evaljs方法类似,但更偏向于执行某些动作或声明某些方法。例如:

lua 复制代码
function main(splash)
  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方法得到的结果。

运行结果如下:

lua 复制代码
Splash Response: "bar"

可以看到,这里我们成功模拟发送POST请求,并发送了表单数据。

  • html方法

此方法用于获取页面的源代码,是一个非常简单且常用的方法,示例如下:

lua 复制代码
function main(splash, args)
  splash:go("https://www.httpbin.org/get")
  return splash:html()
end

运行结果如下:

lua 复制代码
<html><head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">{
  "args": {}, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate", 
    "Accept-Language": "en,*", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/10.0 Safari/602.1", 
    "X-Amzn-Trace-Id": "Root=1-66039ca6-0aa974a63bec11de7a3d386f"
  }, 
  "origin": "58.21.224.175", 
  "url": "https://www.httpbin.org/get"
}
</pre></body></html>
  • png方法

此方法用于获取PNG格式的页面截图,示例如下:

lua 复制代码
function main(splash, args)
  splash:go("https://www.taobao.com")
  return splash:png()
end
  • jpeg方法

此方法用于获取JPEG格式页面截图,示例如下:

lua 复制代码
function main(splash, args)
  splash:go("https://www.taobao.com")
  return splash:jpeg()
end
  • har方法

此方法用于获取页面加载过程的描述信息,示例如下:

lua 复制代码
function main(splash, args)
  splash:go("https://www.taobao.com")
  return splash:har()
end

运行结果如图所示:

  • url 方法

此方法用于获取当前正在访问的URL,示例如下:

lua 复制代码
function main(splash, args)
 	splash:go("https://www.baidu.com")
  return splash:url()
end

运行结果如下:

lua 复制代码
Splash Response: "https://www.baidu.com/"
  • set_user_agent方法

此方法用于设置浏览器的User-Agent,示例如下:

lua 复制代码
function main(splash)
 	splash:set_user_agent('Splash')
  splash:go("http://www.httpbin.org/get")
  return splash:html()
end

这里我们将浏览器的User-Agent属性设置为例Splash,运行结果如下:

lua 复制代码
<html><head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">{
  "args": {}, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate", 
    "Accept-Language": "en,*", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Splash", 
    "X-Amzn-Trace-Id": "Root=1-66040662-00cfb9b47a1b8e381b45aa9f"
  }, 
  "origin": "58.21.224.175", 
  "url": "http://www.httpbin.org/get"
}
</pre></body></html>

可以看到我们设置的User-Agent属性值生效了。

  • select方法

该方法用于选中符合条件的第一个节点,如果有多个节点符合条件,则只返回一个,其参数是CSS选择器。示例如下:

lua 复制代码
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选择器。示例如下:

lua 复制代码
function main(splash)
	local treat = require('treat')
  assert(splash:go("http://quotes.toscrape.com/"))
  assert(splas: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

这里我们通过CSS选择器选中了节点的正文内容,然后遍历所有节点,获取了其中的文本。运行结果如下:

lua 复制代码
Success
Splash Response: Array[10]
0: ""The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.""
1: ""It is our choices, Harry, that show what we truly are, far more than our abilities.""
2: String (length 131)download
"There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle."
3: ""The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.""
4: ""Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.""
5: ""Try not to become a man of success. Rather become a man of value.""
6: ""It is better to be hated for what you are than to be loved for what you are not.""
7: ""I have not failed. I've just found 10,000 ways that won't work.""
8: ""A woman is like a tea bag; you never know how strong it is until it's in hot water.""
9: ""A day without sunshine is like, you know, night.""

可以发现,我们成功获取了10个节点的正文内容。

  • mouse_click方法

此方法用于模拟鼠标的点击操作,参数为坐标值x、y。我们可以直接选中某个节点直接调用此方法,示例如下:

lua 复制代码
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秒,就会返回页面截图,如图所示:

可以看到,我们成功获取了查询后的页面内容,模拟了百度的搜索操作。

7. 调用Splash提供的API

Splash怎样才能和Python程序结合使用并爬取JavaScript渲染的页面?其实,Splash给我们提供了一些HTTP API,我们只需用请求这些API并传递相应的参数即可获取页面渲染后的结果,下面我们学习这些API。

  • render.html

此API用于获取JavaScript渲染的页面的HTML代码,API地址是Splash的运行地址加上此API的名称,例如http://localhost:8050/render.html,我们可以用curl工具测试一下:

lua 复制代码
curl http://localhost:8050/render.html?url=https://www.baidu.com

我们给此API传递了一个url参数,以指定渲染的URL,返回结果即为页面渲染后的源代码。

用Python实现的代码如下:

lua 复制代码
import requests
url = 'http://localhost:8050/render.html?url=https://www.baidu.com'
response = requests.get(url)
print(response.text)

这样就可以成功输出百度页面渲染后的源代码了。

此API还有其他参数,例如wait,用来指定等待秒数。如果要确保页面完全加载出来,就可以设置此参数,例如:

lua 复制代码
import requests
url = 'http://localhost:8050/render.html?url=https://www.taobao.com&amp;wait=5'
response = requests.get(url)
print(response.text)

增加等待时间后,得到响应的时间会相应变长,如这里我们等待大约5秒钟才能获取JavaScript渲染的淘宝页面源代码。

  • render.png

此API用于获取页面截图,其参数比render.html要多几个,例如width和height用来控制截图的宽和高,返回值是PNG格式图片的二进制数据。示例如下:

lua 复制代码
curl http://localhost:8050/render.png?url=https://www.taobao.com&wait=5&width=1000&height=700

这里用Python实现,可以将返回的二进制数据保存为PNG格式图片,代码如下:

lua 复制代码
import requests
url = 'http://localhost:8050/render.png?url=https://www.taobao.com&amp;wait=5&width=1000&height=700'
response = requests.get(url)
with open('taobao.png', 'wb') as f:
    f.write(response.content)

得到图片如下图所示:

这样我们就成功获取了京东首页渲染完成后的页面截图。

  • render.jpeg

此API和render.png类似,不过它返回的是JPEG格式图片的二进制数据。

  • render.har

此API用于获取页面加载的HAR数据,示例如下:

lua 复制代码
curl http://localhost:8050/render.har?url=https://www.jd.com&wait=5

运行结果非常多,是一个JSON格式的数据,里面包含页面加载过程中的HAR数据,如图所示:

  • render.json

此AIP包含前面介绍的所有render相关的API的功能,返回值是JSON格式的数据,示例如下:

lua 复制代码
curl http://localhost:8050/render.json?url=https://www.httpbin.org

运行结果如下:

lua 复制代码
(base) bruce_liu@localhost ~ % curl http://localhost:8050/render.json?url=https://www.httpbin.org
{"url": "https://www.httpbin.org/", "requestedUrl": "https://www.httpbin.org/", "geometry": [0, 0, 1024, 768], "title": "httpbin.org"}% 

可以看到,这里返回了JSON格式的请求数据。我们可以通过传入不同的参数控制返回的结果。例如,传入html=1,返回结果回增加页面源代码;传入png=1,返回结果回增加PNG格式的页面截图;传入har=1,返回结果会增加页面的HAR数据。例如:

lua 复制代码
curl http://localhost:8050/render.json\?url\=https://www.httpbin.org\&html\=1\&har\=1

这样返回的结果中变会包含页面源代码和HAR数据。

  • execute

此API才是最为强大的API。用此API即可实现于Lua脚本的对接。要爬取一般的JavaScript渲染页面,使用前面的render.html和render.png等API就足够了,但如果要实现一些交互操作,这些API还是心有余而力不足,就需要使用execute了。

先实现一个最简单的脚本,直接返回数据:

lua 复制代码
function main(splash, args)
  return 'hello'
end

然后将此脚本转化为URL编码后的字符串,拼接到execute后面,示例如下:

lua 复制代码
curl http://localhost:8050/execute?lua_source=function%20main%28splash%2C%20args%29%0A%20%20return%20%27hello%27%0Aend

运行结果如下:

lua 复制代码
hello

这里我们通过lua_source参数传递了转码后的Lua脚本,通过execute获取了脚本最终的执行结果。我们更加关心的是如何利用Python实现上述过程,如果用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)

运行结果如下:

python 复制代码
hello

这里我们用Python中的三引号将Lua脚本扩起来,然后用urllib.parse模块里的quote方法对脚本进行URL转码,之后构造了请求URL,并将其作为lua_source参数传递,这样运行结果就会显示Lua脚本执行后的结果。

我们再通过实例看一下:

python 复制代码
import requests
from urllib.parse import quote

lua = '''
function main(splash, args)
    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)

运行结果如下:

python 复制代码
{"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-6604afde-277e2b9c774cf6837e3e12cd\"\n  }, \n  \"origin\": \"58.21.224.175\", 
 \n  \"url\": \"http://www.httpbin.org/get\"\n}\n",
 "status": 200, "url": "http://www.httpbin.org/get"}

可以看到,返回结果是JSON形式的,我们成功获取了请求URL、状态码和页面源代码。

这样,所有网页的动态渲染、模拟点击、表单提交、页面滑动、延时等待后的结果均可以自由控制获取细节,获取页面源代码和截图也都不在话下。

  1. 负载均衡配置

    要配置Splash服务的负载均衡,您可以考虑使用一种常见的负载均衡器(如Nginx、HAProxy等)将请求分发到多个Splash实例。下面是一个简单的示例,演示如何利用Nginx作为负载均衡器来配置Splash服务的负载均衡:

    1. 安装和配置Nginx

      • 安装Nginx并打开配置文件进行编辑。
    2. 配置Nginx作为负载均衡器

      • 在Nginx配置文件中添加类似以下内容的配置:

        upstream splash_servers {
        server localhost:8050;
        server localhost:8051;
        server localhost:8052;
        # Add more Splash instances as needed
        }

        server {
        listen 80;
        location / {
        proxy_pass http://splash_servers;
        }
        }

      这里,upstream splash_servers定义了三个Splash服务实例的地址和端口(根据需求添加更多实例),proxy_pass指令将请求代理到这些Splash实例中的一个。

    3. 重启Nginx服务

      • 验证Nginx配置的正确性,并重启Nginx服务使更改生效。
    4. 测试负载均衡

      • 确保Nginx已正确配置负载均衡,并且请求能够平衡地分配给不同的Splash实例。可以通过向Nginx发送请求并观察各个Splash实例的响应来进行测试。

    通过这样的配置,Nginx将能够在多个Splash实例之间均衡分配负载,从而提高可用性和性能。根据实际情况,您可以进一步优化负载均衡器的配置,以满足特定的需求和规模。

    更多体验在小蜜蜂AI网站获取,网址:https://zglg.work

相关推荐
郭庆汝4 小时前
pytorch、torchvision与python版本对应关系
人工智能·pytorch·python
思则变7 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络8 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find9 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取10 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
精灵vector12 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习12 小时前
Python入门Day2
开发语言·python
Vertira12 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉12 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗12 小时前
黑马python(二十四)
开发语言·python