首页 > 其他分享 >Splash

Splash

时间:2024-02-02 19:22:06浏览次数:23  
标签:function end url args splash main Splash

Splash使用

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

一,安装

本安装使用docker

1.1拉去镜像

docker pull scrapinghub/splash

1.2运行

docker run -p 8050:8050 scrapinghub/splash

image-20240127210715057

二,使用

(一)Splash Lua 脚本

Splash 可以通过 Lua 脚本执行一系列渲染操作,这样我们就可以用 Splash 来模拟浏览器的操作了,Splash Lua 基础语法如下:

function main(splash, args)           # main()方法是入口,名称必须固定的,Splash默认调用这个方法
    splash:go("http://www.baidu.com")  # go()方法用于加载页面
    splash:wait(0.5)                   # wait()方法用于等待指定的时间
    local title = splash:evaljs("document.title")   # evaljs()方法用于传入并执行JavaScript脚本,这里将执行结果赋值给title变量
    return title                             # 返回title变量的值,结果是一个字符串:"百度一下,你就知道"
 end      

demo:

function main(splash, args)
  local example_urls = {"www.baidu.com", "www.hao123.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

image-20240127212218657

(二)Splash对象属性

main()方法的第一个参数是splash,这个对象非常重要,它类似于Selenium中的WebDriver对象,我们可以调用它的一些属性和方法来控制加载过程。

1.agrs

该属性可以获取加载时配置的参数,比如URL,如果为GET请求,它还可以获取GET请求参数;如果为POST请求,它可以获取表单提交的数据。Splash也支持使用第二个参数直接作为args

function main(splash, args)
    local url = args.url
    return {url=url}
end

等价于

function main(splash, args)
    local url = splash.args.url
    return {url=url}
end

image-20240130183748193

2.js_enabled

这个属性是Splash的JavaScript执行开关,可以将其配置为true或false来控制是否执行JavaScript代码,默认为true。例如,这里禁止执行JavaScript代码如下。

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

结果:

{
    "error": 400,
    "description": "Error happened while executing Lua script",
    "info": {
        "error": "unknown JS error: None",
        "message": "[string \"function main(splash, args)\r...\"]:4: unknown JS error: None",
        "source": "[string \"function main(splash, args)\r...\"]",
        "js_error_message": null,
        "splash_method": "evaljs",
        "type": "JS_ERROR",
        "line_number": 4
    },
    "type": "ScriptError"
}

调用了evaljs()方法执行JavaScript代码,此时运行结果就会抛出异常。

不过一般来说,不用设置此属性,默认开启即可。

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

结果:

{
    "error": 400,
    "description": "Error happened while executing Lua script",
    "info": {
        "error": "network5",
        "message": "Lua error: [string \"function main(splash)\r...\"]:3: network5",
        "source": "[string \"function main(splash)\r...\"]",
        "line_number": 3,
        "type": "LUA_ERROR"
    },
    "type": "ScriptError"
}

这里将超时时间设置为0.1秒。如果在0.1秒之内没有得到响应,就会抛出异常。此属性适合在网页加载速度较慢的情况下设置。如果超过了某个时间无响应,则直接抛出异常并忽略即可。

4.images_enabled

此属性可以设置图片是否加载,默认情况下是加载的。禁用该属性后,可以节省网络流量并提高网页加载速度。但是需要注意的是,禁用图片加载可能会影响JavaScript渲染。因为禁用图片之后,它的外层DOM节点的高度会受影响,进而影响DOM节点的位置。因此,如果JavaScript对图片节点有操作的话,其执行就会受到影响。

另外值得注意的是,Splash使用了缓存。如果一开始加载出来了网页图片,然后禁用了图片加载,再重新加载页面,之前加载好的图片可能还会显示出来,这时直接重启Splash即可。

function main(splash, args)
  splash.images_enabled = false
  assert(splash:go('https://www.jd.com'))
  return {png=splash:png()}
end

这样返回的页面截图就不会带有任何图片,加载速度也会快很多。

5.plugins_enabled

此属性可以控制浏览器插件(如Flash插件)是否开启。默认情况下,此属性是false,表示不开启。可以使用如下代码控制其开启和关闭。

splash.plugins_enabled = true/false

6.scroll_position

通过设置此属性,我们可以控制页面上下或左右滚动。这是一个比较常用的属性。

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

如果要让页面左右滚动,可以传入x参数,代码如下:

splash.scroll_position = {x=100, y=200}

(三)Splash对象方法

1.go()

请求某个链接,可传入请求头、表单等数据.

ok,reason = splash:go{url, baseurl=nil, headers=nil, http_method="GET", body=nil , formdata=nil}
  • url:请求的url
  • baseurl:可选参数,默认为空,表示资源和加载相对路径
  • headers:可选参数,默认为空,表示请求头
  • http_method:可选参数,默认为GET
  • body:可选参数,默认为空,POST的时候的表单数据,使用的content-type为application/json
  • formdata:可选参数,默认为空,POST的时候的表单数据,使用的content-type为application/x-www-form-urlencoded

2.wait()

控制页面等待时间.

ok, reason = splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}
  • time:等待的时间
  • cancel_on_error:可选参数,默认false,表示发生错误加载,就停止等待
  • cancel_on_redirect:可选参数,默认false,表示发生重定向就停止等待,并返回重定向结果

3.evaljs()

执行JavaScript代码后,返回最后一条JavaScript语句返回的结果

result = splash:evaljs(js)

4.runjs()

声明JavaScript定义的语句块,通过evaljs()调用

function main(splash, args)
  splash:go(args.url)
  splash:runjs("foo = function(){return 'hello'}")
  local result = splash:evaljs("foo()")
  return result
end

5.autoload()

设置每个页面访问时自动加载的对象,可以是JavaScript代码或库,但是不执行操作,执行调用evaljs()

ok,reason = splash:autoload{source_or_url}
  • source_or_url:js代码或js库链接
  • source:js代码
  • url:js库链接

6.call_later()

设置定时任务和延时执行,如下在go访问后使用wait(3.0)等待3秒才返回所有截图,期间设置0.2秒获取截图,中间等待1秒,1.2秒的时候再次获取截图,最后3秒后返回所有截图

function main(splash, args)
  local snapshots = {}
  local timer = splash:call_later(function()
    snapshots["a"]=splash:png()
    splash:wait(1)
    snapshots["b"]=splash:png()
  end,0.2)
  splash:go("https://www.taobao.com")
  splash:wait(3.0)
  return snapshots
end

7.http_get()

模拟发送http的get请求

response = splash:http_get(url,headers=nil,follow_redirects=true)
  • url:请求的url
  • headers:可选参数,默认为空,请求头
  • follow_redirects:可选参数,表示是否启动自动重定向,默认true

8.http_post()

发送post请求,需要body参数

response = splash:http_post{url, headers =「1il, follow_redirects=true, body=nil}
  • url:请求的url
  • headers:可选参数,默认为空,请求头
  • follow_redirects:可选参数,表示是否启动自动重定向,默认true
  • body:可选参数,即表单参数,默认为空
function main(splash, args)
  local treat = require("treat")
  local json = require("json")
  local response = splash:http_post{args.url,
    body=json.encode({name="aha"}),
    headers={["content-type"]="application/json"}
  }
  return {
    html = treat.as_string(response.body),
    url = response.url,
    status = response.status
  }
end

9.set_content()

设置页面内容

function main(splash) 
    assert(splash:set_content("<html><body><hl>hello</hl></body></html>")) 
    return splash: png ()
end 

10.html()

返回获取的页面源码信息

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

png(),jpeg(),har(),url()

function main(splash, args) 
    splash:go("https:/taobao.com") 
    return splash: png() 
end

function main(splash, args) 
    splash:go("https:/taobao.com") 
    return splash: jpeg() 
end

function main(splash, args) 
    splash:go("https:/taobao.com") 
    return splash: har() 
end

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

11.get_cookies()

获取当前访问链接的cookies

function main(splash, args) 
    splash:go("https:/taobao.com") 
    return splash: get_cookies() 
 end

12.add_cookies()

添加cookies

cookies = splash:add_cookie{name, value, path=nil, domain=nil, expires=nil, httpOnly=nil, secure=nil}

demo

function main(splash) 
  splash:add_cookie{"sessionid","23746Sghgfsd ","/", domain="http://example.com"}
  splash:go("http://example.com/") 
  return splash:html()
end

13.clear_cookies()

清除cookies

function main(splash, args) 
    splash:go("https:/taobao.com") 
  splash:clear_cookies()
    return splash: get_cookies() 
 end

14.get_viewport_size()

获取当前浏览器的大小

function main(splash, args) 
    splash:go("https:/taobao.com") 
    return splash:get_viewport_size()
 end

15.set_viewport_size()

设置当前浏览器的大小

function main(splash, args) 
  splash:set_viewport_size(1200,800)
  assert(splash:go("https:/taobao.com"))
  return splash:png()
 end

16.set_viewport_full()

设置浏览器全屏显示

function main(splash, args) 
    splash:set_viewport_full()
  assert(splash:go("https:/taobao.com"))
  return splash:png()
 end

17.set_user_agent()

设置浏览器的user_agent

function main(splash, args) 
    splash:set_user_agent('Splash')
  assert(splash:go("http://httpbin.org/get"))
  return splash:html()
 end

18.set_custom_headers()

设置请求头信息

function main(splash, args) 
    splash:set_custom_headers({
      ["User-Agent"] = "Splash",
      ["Sitle"] = "Splash",
    })
  assert(splash:go("http://httpbin.org/get"))
  return splash:html()
 end

19.select()

返回选中符合条件的第一个节点,参数是CSS选择器

function main(splash, args) 
    splash:go("https://www.baidu.com/")
  input = splash:select("#kw")
  input:send_text("Splash")
  splash:wait(3)
  return splash:png()
 end

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

21.mouse_click()

模拟鼠标点击事件

function main(splash) 
    splash:go("https://www.baidu.com")
  input = splash:select("#kw")
  input:send_text('Splash')
  submit = splash:select('#su')
  submit:mouse_click()
  splash:wait(3)
  return splash:png()
end

三,Splash API调用

如何才能利用Splash渲染页面呢?怎样才能和Python程序结合使用并抓取JavaScript渲染的页面呢?

其实Splash给我们提供了一些HTTP API接口,我们只需要请求这些接口并传递相应的参数即可。

1. render.html

此接口用于获取JavaScript渲染的页面的HTML代码,接口地址就是Splash的运行地址加此接口名称。

例如http://localhost:8050/render.html。

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

2.render.png

此接口可以获取网页截图,其参数比render.html多了几个,比如通过width和height来控制宽高,它返回的是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)

3.render.jpeg

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

另外,此接口比render.png多了参数quality,它用来设置图片质量。

4.render.har

此接口用于获取页面加载的HAR数据

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

它的返回结果非常多,是一个JSON格式的数据,其中包含页面加载过程中的HAR数据。

5.render.json

此接口包含了前面接口的所有功能,返回结果是JSON格式。

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

可以看到,这里以JSON形式返回了相应的请求数据。

我们可以通过传入不同参数控制其返回结果。比如,传入html=1,返回结果即会增加源代码数据;传入png=1,返回结果即会增加页面PNG截图数据;传入har=1,则会获得页面HAR数据。

import requests
url = 'http://localhost:8050/render.json?url=https://httpbin.org&html=1&har=1'
response = requests.get(url)
print(response.text)

这样返回的JSON结果会包含网页源代码和HAR数据

可参考:https://splash.readthedocs.io/en/stable/api.html#render-json

5.⭐execute

此接口才是最为强大的接口。前面说了很多Splash Lua脚本的操作,用此接口便可实现与Lua脚本的对接。

前面的render.html和render.png等接口对于一般的JavaScript渲染页面是足够了,但是如果要实现一些交互操作的话,它们还是无能为力,这里就需要使用execute接口了。

使用步骤:

①lua脚本

function main(splash)
    return 'hello'
end

②改为url编码、

使用网站:在线编码转换 (oschina.net)

function%20main(splash)%0A%20%20%20%20return%20'hello'%0Aend

③运行语句:

curl http://localhost:8050/execute?lua_source=function+main%28splash%29%0D%0A++return+%27hello%27%0D%0Aend

④构建python

import requests
from urllib.parse import quote
 
lua = '''
function main(splash, args)
  local treat = require("treat")
  local response = splash:http_get("http://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)

四,Splash负载均衡配置

假设有多台服务器在8050端口配置了 splash 服务,都是通过 docker 的 splash 开启,都可以使用服务。

1.配置负载均衡

接下来,可以选用任意一台带有公网 IP 的主机来配置负载均 首先,在这台主机上装好 Nginx,

然后修改 Nginx 的配置文件 nginx.conf,添加如下内容:

http {
    upstream splash {
# least_conn 代表最少链接负载均衡,它适合处理请求处理时间长短不一造成服务器过载的情况
# ip_hash 服务器根据请求客户端的 IP 地址进行散列计算,确保使用同一个服务器响应请求,这种
# 策略适合有状态的服务,比如用户登录后访问某个页面的情形
# server 119.45.0.45:8050; 可以指定权重 server 119.45.0.45:8050 weight=4;
            least_conn;
            server 119.45.0.45:8050;
            server 167.179.88.120:8050;
        }
    server {
            listen 8050;
            location / {
                proxy_pass http://splash;
            }
        }
}

2.配置认证

现在 Splash 是可以公开访问的,如果不想让其公开访问,还可以配置认证,这仍然借助于 Nginx

可以在 server 的 location 字段中添加 auth_basic 和 auth_basic_user_file 字段,具体配置如下:

http {
    upstream splash {
            least_conn;
            server 119.45.0.45:8050;
            server 167.179.88.120:8050;
        }
    server {
            listen 8050;
            location / {
                proxy_pass http://splash;
                auth_basic "Restricted";
                auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
            }
        }
}                      

这里使用的用户名和密码配置放置在 /etc/nginx/conf.d 目录下,我们需要使用 htpasswd 命令创建

例如,创建一个用户名为 admin 的文件,相关命令如下:

htpasswd -c .htpasswd admin

接下来就会提示我们输入密码,输入两次之后,就会生成密码文件,其内容如下:

cat .htpasswd
admin:SZBxQrorCqwbc

配置完成后,重启 Nginx 服务:

sudo nginx -s reload

3.测试

import requests
from urllib.parse import quote
import re
 
lua = '''
function main(splash, args)
  local treat = require("treat")
  local response = splash:http_get("http://httpbin.org/get")
  return treat.as_string(response.body)
end
'''
 
 
url = 'http://127.0.0.1:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
// 如果配置了密码  response = requests.get(url, auth=('admin', 'admin'))
ip = re.search('(\d+\.\d+\.\d+\.\d+)', response.text).group(1)
print(ip)
 

标签:function,end,url,args,splash,main,Splash
From: https://www.cnblogs.com/xueyitian/p/18003722

相关文章

  • 界面控件DevExpress WPF Splash Screen,让应用启动画面更酷炫!
    DevExpressWPF的SplashScreen组件可以为应用程序创建十分酷炫的启动屏幕,提高用户在漫长的启动操作期间的体验!P.S:DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用......
  • Ubuntu22.04运行Splash Docker镜像报错,cloud not load the Qt platform xcb in even t
    一、问题描述Ubuntu22.04运行SplashDocker镜像报错,cloudnotloadtheQtplatformxcbineventhoughitwasfound奇怪的地方在于,停止运行,重新执行同样的语句,即恢复正常。本文只做了问题记录,没有深入研究原因。sudodockerrun-it-p8050:8050scrapinghub/splash二......
  • 短说PC版 3.0.0测试版发布|新增学院系统、好友邀请、支持Unsplash图库、支持积分打赏
    Hi大家好,我是给你们带来惊喜的运营小番茄。又见面了,本月更新频繁,移动端和PC端均有大功能的更新,测试版尚不交付客户更新,请等待正式版发布,但我们可以先了解一下本次3.0的新功能哦~本期更新为短说PC端3.0.0测试版。本次V3.0.0版本主要更新的功能有学院系统(万众期待)、好友邀请、支持Un......
  • .Net设置SplashScreen,在高DPI下不居中的解决方案
    .Net设置SplashScreen,在高DPI下不居中的解决方案根据.Net官方文档,设置图片类型的软件的启动屏幕非常简单,只需要将图片放在工程里,并将图片的生成操作设置为SplashScreen后即可。但是这个办法在高DPI屏幕中没有适应,图片显示的位置不居中,对于强迫症来说会非常非常难受。查......
  • Splash与requests结合
    Splash与requests结合render.html此接口用于获取JavaScript渲染的页面的HTML代码,接口地址就是Splash的运行地址加此接口名称,例如http://localhost:8050/render.htmlimportrequestsdeffunc1():'''render.html返回一个html结果'''url='https://www.xxxx......
  • Splash与Scrapy结合
    Splash与Scrapy结合scrapy-splash教程—splash中文文档0.1文档https://splash-cn-doc.readthedocs.io/zh_CN/latest/scrapy-splash-toturial.html安装scrapy-splash库pipinstallscrapy-splash==0.8.0配置splash服务(以下操作全部在settings.py)使用splash解析,要在配......
  • Splash反爬
    为什么要反爬爬虫:使用任何技术手段,批量获取网站信息的一种方式。关键在于批量反爬虫:使用任何技术手段,阻止别人批量获取自己网站信息的一种方式。关键也在于批量因爬虫的访问频率过高影响服务器的运行影响别人业务导致服务器宕机单一的DoS攻击一般是采用一对一方式的......
  • 全球最大照片网站 Unsplash 开放图片检索数据集
    By超神经内容概要:全球最大的照片网站 Unsplash宣布平台已经开放了超过20万名摄影师的近200万张免费图片的,并开放了两个图片检索结果的数据集。关键词:数据集图片搜索图像分类Unsplash是世界上最大的照片摄影网站之一,由全世界20多万摄影师参与,贡献了数百万张高清优质的摄......
  • 学完Scrapy-Splash秒变爬虫大佬
    在做爬虫的时候,大多数的网页中会存在数据动态加载的部分,而且多数都是后期渲染上的。正常情况下爬虫程序仅能爬取被渲染过的数据。因此我们看到的数据也许并非是爬虫直接获......
  • splash的使用
    splash是一个JavaScript渲染服务,利用它可以爬取动态渲染的页面一、简介功能异步处理多个网页的渲染过程可以获取渲染后页面的源代码、截图、以及页面的加载过程信息......