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

news2024/11/29 2:53:12

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的加载等,最终呈现的页面和在浏览器中看到的完全一致。

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

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脚本的入口和执行方式。

  • 入口及返回值

基本实例:

function main(splash, args)
  splash:go("http://www.baidu.com")
  splash:wait(0.5)
  local title = splash:evaljs("document.title")
  return {title=title}
  
end

Screenshot 2024-03-26 at 21.49.12.png

将这段代码粘贴到上图中的代码编辑区域,然后单击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个网站的页面截图,如下图所示:

Screenshot 2024-03-28 at 08.12.42.png

代码中调用的wait方法类似于Python中的sleep方法,参数是等待的秒数。当Splash执行到此方法时,会转而处理其他任务,在等待参数指定的时间后再回来继续处理。Lua脚本中的字符串拼接和Python中不同,它使用的是“…“操作符,而不是”+”。

5. 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

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

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),代表不检测超时。示例如下:

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

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

{
    "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属性的示例如下:

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像素值,运行结果如下图所示:

在这里插入图片描述

6. splash对象的方法

  • go方法

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

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中包含错误的原因,否则代表页面加载成功,示例如下:

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

<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方法

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

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

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

Splash Response: "There are 148 DIVs"
  • evaljs方法

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

result = splash:evaljs(js)

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

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

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方法得到的结果。

运行结果如下:

Splash Response: "bar"

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

  • html方法

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

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

运行结果如下:

<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格式的页面截图,示例如下:

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.taobao.com")
  return splash:har()
end

运行结果如图所示:

在这里插入图片描述

  • url 方法

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

function main(splash, args)
 	splash:go("https://www.baidu.com")
  return splash:url()
end

运行结果如下:

Splash Response: "https://www.baidu.com/"
  • 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,运行结果如下:

<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选择器。示例如下:

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(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选择器选中了节点的正文内容,然后遍历所有节点,获取了其中的文本。运行结果如下:

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。我们可以直接选中某个节点直接调用此方法,示例如下:

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工具测试一下:

curl http://localhost:8050/render.html?url=https://www.baidu.com

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

用Python实现的代码如下:

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.taobao.com&amp;wait=5'
response = requests.get(url)
print(response.text)

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

  • render.png

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

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

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

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数据,示例如下:

curl http://localhost:8050/render.har?url=https://www.jd.com&wait=5

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

在这里插入图片描述

  • render.json

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

curl http://localhost:8050/render.json?url=https://www.httpbin.org

运行结果如下:

(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数据。例如:

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了。

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

function main(splash, args)
  return 'hello'
end

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

curl http://localhost:8050/execute?lua_source=function%20main%28splash%2C%20args%29%0A%20%20return%20%27hello%27%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, 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)

运行结果如下:

{"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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unix中的进程和线程-1

目录 1.如何创建一个进程 2.如何终止进程 2.2遗言函数 3.进程资源的回收 4.孤儿进程和僵尸进程 孤儿进程 (Orphan Process)&#xff1a; 僵尸进程 (Zombie Process)&#xff1a; 代码示例&#xff1a; 5. 进程映像的更新 在Linux中&#xff0c;进程和线程是操作系统进行工作调…

【Docker笔记02】【常用软件安装】

一、前言 本系列是根据 B 站 尚硅谷 Docker 视频 学习记录笔记。因为没有视频课件&#xff0c;部分内容摘自 https://www.yuque.com/tmfl/cloud/dketq0。 本系列仅为自身学习笔记记录使用&#xff0c;记录存在偏差&#xff0c;推荐阅读原视频内容或本文参考笔记。 本文主要介…

Adobe ColdFusion 任意文件读取漏洞复现(CVE-2024-20767)

0x01 产品简介 Adobe ColdFusion是美国奥多比(Adobe)公司的一套快速应用程序开发平台。该平台包括集成开发环境和脚本语言,将可扩展、改变游戏规则且可靠的产品的愿景变为现实。 0x02 漏洞概述 由于 Adobe ColdFusion 的访问控制不当,未经身份认证的远程攻击者可以构造恶…

go语言基础学习-通道(续)

1、如何有序的从通道取值 第一种 判断ok的值 package day13import "fmt"func D131() {ch1 : make(chan int)// 开始goroutine将0-100的数据发送到ch1中go func() {for i : 0; i < 100; i {ch1 <- i}close(ch1)}()for {i, ok : <-ch1 // 通道关闭后再取值o…

计算机网络-HTTP相关知识(一)

HTTP基础 基本概念&#xff1a;HTTP是一种计算机之间交流通信的规范&#xff0c;它允许数据在两点之间传输&#xff0c;这个过程可以包括中转或接力。HTTP不仅仅包括文本&#xff0c;还可以包括图片、音频等超文本。状态码&#xff1a;HTTP状态码分为五类&#xff1a; 2xx&…

移植DM9000驱动至内核(linux-2.6.32.24)

目录 概述 1 移植 DM9000驱动 1.1 添加设备驱动代码 1.2 调整 DM9000 所用的位宽寄存器 1.3 配置MAC地址 2 配置和编译DM9000 Driver至内核 3 验证 概述 本文主要介绍如何移植DM9000的驱动到linux-2.6.32.24内核&#xff0c;笔者详细记录了内核移植过程中遇见的问题&…

【InternLM 实战营第二期笔记】InternLM1.8B浦语大模型趣味 Demo

体验环境 平台&#xff1a;InternStudio GPU&#xff1a;10% 配置基础环境 studio-conda -o internlm-base -t demo 与 studio-conda 等效的配置方案 conda create -n demo python3.10 -y conda activate demo conda install pytorch2.0.1 torchvision0.15.2 torchaudio2…

如何使用 Python 本地客户端操作读写云服务器 Redis 缓存数据库详细教程(更新中)

Redis 基本概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的使用 ANSI C 语言编写的、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库&#xff0c;并提供多种语言的 API。它通常被称为数据结构服务器&#xff0c;因为值&#xff08;value…

Docker配置Mysql

1.首页搜索mysql镜像 2.选择对应版本的MySQL&#xff0c;点击pull 3.pull完成以后&#xff0c;点击images&#xff0c;这里可以看到刚刚pull完成的mysql版本 4.打开命令界面&#xff0c;运行命令 docker images ,查看当前已经pull的images 5.运行命令设置mysql docker run -it…

PHP三种方式读取RSA密钥加解密、签名验签完整教程

目录 第一步、生成公私钥 第二步、三种方式读取RSA密钥 第1种&#xff1a;公私钥弄成一行&#xff0c;必须一行没有空格和换行 第2种&#xff1a;直接复制生成公私钥 第3种;复制密钥存储为.pem文件后缀 第三步、RSA加解密 第四步、RSA签名以及验证签名 第五步、封装完整…

[图像处理] MFC载入图片并进行二值化处理和灰度处理及其效果显示

文章目录 工程效果重要代码完整代码参考 工程效果 载入图片&#xff0c;并在左侧显示原始图片、二值化图片和灰度图片。 双击左侧的图片控件&#xff0c;可以在右侧的大控件中&#xff0c;显示双击的图片。 初始画面&#xff1a; 载入图片&#xff1a; 双击左侧的第二个控件…

QT记事本

QT记事本 1.概述 2.界面  2.1 界面布局  2.2 UI美化stylesheet   2.2.1 准备   2.2.2 stylesheet   2.2.3 效果 2.3 窗口大小调整与子控件自适应 3.信号与槽  3.1 简述  3.2 信号与槽设置   3.2.1 UI控件设置   3.2.2 UI转到槽&#xff08;自动连接&am…

Go 源码之 gin 框架

Go 源码之 gin 框架 go源码之gin - Jxy 博客 一、总结 gin.New()初始化一个实例&#xff1a;gin.engine&#xff0c;该实例实现了http.Handler接口。实现了ServeHTTP方法 注册路由、注册中间件&#xff0c;调用addRoute将路由和中间件注册到 methodTree 前缀树&#xff08;节…

flutter官方案例context_menus

1&#xff1a;根据项目中的案例进行部署 2&#xff1a;运行查看有什么用&#xff0c;可不可以直接复制粘贴 案例地址 https://github.com/flutter/samples/tree/main/context_menus案例展示方法 直接把这个文件夹中的文件复制到lib文件夹中 3&#xff0c;19&#xff0c;4的fl…

关系型数据库mysql(10)MHA的高可用

一. MHA 的相关知识 1. 什么是 MHA MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。MHA 的出现就是解决MySQL 单点的问题。MySQL故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障切换操作。MHA能在故障…

[Windows]防火墙,出入站规则失效。

场景&#xff1a; 因为具体需要&#xff0c;在内网中&#xff0c;不想别人发现我们的nacos端口8848&#xff0c;因此我们设置了入站规则&#xff0c;特定的ip地址才能访问。但是实际测试中发现并不起作用。。。 经过一番排查得到一下结果。 为什么有些应用绕过了防火墙配置 有…

JimuReport积木报表 v1.7.4 公测版本发布,免费的JAVA报表工具

项目介绍 一款免费的数据可视化报表&#xff0c;含报表和大屏设计&#xff0c;像搭建积木一样在线设计报表&#xff01;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; Web 版报表设计器&#xff0c;类似于excel操作风格&#xff0c;通过拖拽完成报…

Linux速览(2)——环境基础开发工具篇(其一)

本章我们来介绍一些linux的常用工具 目录 一. Linux 软件包管理器 yum 1.什么是软件包? 2. 查看软件包 3. 如何安装软件 4. 如何卸载软件 5.yum补充 6. 关于 rzsz 二. Linux编辑器-vim使用 1. vim的基本概念 2. vim的基本操作 3. vim正常模式命令集 4. vim末行模式…

计算机网络-从输入网址到访问网站的全过程

当我们在浏览器中输入一个网址并按下回车键时&#xff0c;会发生一系列复杂的过程&#xff0c;最终使我们能够看到网页的内容。以下是这个过程的详细步骤&#xff1a; 客户端&#xff1a;首先&#xff0c;用户在浏览器中键入网址&#xff0c;然后浏览器会根据这个网址生成一个H…

vultr ubuntu 服务器远程桌面安装及连接

一. 概述 vultr 上开启一个linux服务器&#xff0c;都是以终端形式给出的&#xff0c;默认不带 ui 桌面的&#xff0c;那其实对于想使用服务器上浏览器时的情形不是很好。那有没有方法在远程服务器安装桌面&#xff0c;然后原程使用呢&#xff1f;至少ubuntu的服务器是有的&am…