基于splash的爬虫_02

目录

splash脚本

自己编写第一个Lua脚本

异步处理

splash对象属性

1.args属性

2.js_enable属性

 3.resource_timeout属性

4.images_enabled属性

 5.plugins_enabled属性

 6.scroll_position属性

 go方法

wait方法

jsfunc方法

evaljs方法

runjs方法

autoload方法

call_later方法

http_get方法

http_post方法

set_content方法

html方法

png方法

jpeg方法

har方法

其他方法

1.url方法

2.get_cookies方法

3.add_cookie方法

4.clear_cookie方法

5.get_viewport_size方法

6.set_viewport_size方法

7.set_viewport_full方法

8.set_user_agent方法

9.set_custom_headers方法

CSS选择器

select方法

select_all方法

 模拟鼠标与键盘动作

Splash HTTP API

1.render.html

2.render.png

3.render.jpeg

4.render.har

5.render.json

6.execute


splash脚本

splash可以通过Lua脚本执行一系列渲染操作,这条可以使用splash模拟浏览器的操作

自己编写第一个Lua脚本

main方法是Lua脚本的入口方法,通常有2个参数:splash和args,下面的例子只使用splash参数的go方法

使用go方法访问京东商城首页,获取其标题

function main(splash, args)
  --访问京东商城的首页
  splash:go("https://www.jd.com")
  --等待0.5秒
  splash:wait(0.5)
  --获取京东商城首页的标题,并将标题赋给一个本地变量
  local title=splash:evaljs("document.title")
  --以字典形式返回京东商城首页的标题
  return {
    title=title
  }
end

点击Render me运行Lua脚本,输出结果: 

 PS:main方法可以返回多种形式的数据,如普通的字符串,或一个字典形式的值

异步处理

go方法是通过异步方式访问页面,不过go方法并不能指定异步回调方法,所以在调用go方法后,需要使用wait方法等待一会,这样给页面加载一定时间

例子:对Lua数组进行迭代,得到数组中的URL,组合完整URL,然后通过go方法访问这些URL,并得到每一个URL的页面

function main(splash, args)
  --定义一个Lua数组,数组元素是URL的一部分
  local urls={"www.baidu.com","www.jd.com"}
	--定义保存截图的字典变量
  local results={}
  --对URL数组进行迭代
  for index,url in ipairs(urls) do
    --访问对应的URL,如果ok为nil,所以有错误,reason是错误原因
    local ok,reason=splash:go("https://"..url)
    if ok then
      --等待1秒
      splash:wait(1)
      --得到当前页面的截图
      	results[url]=splash:png()
		end
	end  
  return results
end

结果输出两张截图

 PS:

  1. Lua中的数组和字典使用大括号{...}
  2. go方法是异步执行,不过需要用go方法的返回值ok判断是否请求成功,如果ok为nil,表明请求成功
  3. wait方法相当于Python语言的sleep方法,让线程等待一段时间,单位是秒

splash对象属性

main方法包含2个参数,第1个参数是splash,这个参数相当于Selenium中得WebDriver对象,可以调用Splash对象的一些属性和方法来控制加载过程,本节介绍Splash对象中得常用属性

1.args属性

该属性可以获取加载时配置的参数,如URL
如果是GET请求,还可以获取GET请求参数,如果是POST请求,可以用来获取表单的数据

例子:通过args属性获取URL

function main(splash)
	local url=splash.args.url
end

main方法也支持第2个参数直接作为args

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

2.js_enable属性

该属性控制是否可以执行JavaScript代码,默认为true
如果设定为false,那么无法使用evaljs方法执行JavaScript代码

function main(splash, args)
  splash:go("https://www.jd.com")
  --禁止执行JavaScript代码
  splash.js_enabled=false
  --会抛出异常
  local title=splash:evaljs("document.title")
  return {
    title=title
  }
end

 3.resource_timeout属性

该属性可以设置加载的时间,单位是秒
如果设置为0或者nil(相当于python的None),表示不检测超时
在网页加载慢的时候可以加该属性,防止程序等待时间过长

function main(splash, args)
  splash.resource_timeout=0.01
  --必须使用assert方法才能抛出异常
  assert(splash:go("https://www.jd.com"))
  local title=splash:evaljs("document.title")
  return {
    title=title
  }
end

4.images_enabled属性

该属性用于设置图片是否可以加载,默认为true,表示加载图片.如果将该属性设置为false,则在加载页面时不会加载图片,这样显示的速度会更快.不过要注意的是,如果禁止加载图片,页面的布局可能会改变,而且可能会影响JavaScript渲染.因为禁止加载图片后,包含图片的外层DOM节点的高度会受到影响,进而影响DOM节点的位置,所以如果JavaScript对图片节点有操作,就可能会受到影响

另外,由于Splash使用了缓存,所以如果图片一开始加载了出来,那么禁用了图片加载后,再重新加载页面,之前已经加载过的图片可能还会显示出来,这时只需要重启Splash就可以

function main(splash, args)
  --禁止加载图片
  splash.images_enabled=false
  splash:go("https://www.jd.com")
  png=splash.png()
  return {
    png
  }
end

 5.plugins_enabled属性

该属性用于控制浏览器插件(如Flask插件)是否启动.在默认情况下,该属性是false,表示不开启动浏览器插件,如果设置为true,表示开启浏览器插件

 6.scroll_position属性

该属性用于控制页面上下或者左右滚动.这是一个比较常用的属性.该属性值是一个字典类型,key为x表示页面水平滚动的位置,key为y表示页面垂直滚动的位置

function main(splash, args)
  splash:go("https://www.jd.com")
  --将京东商城首页在垂直方向滚动到500的位置
  splash.scroll_position={y=500}
  return splash:png()
end

 go方法

该方法用于请求某个链接,而且可以指定http方法,目前支持get和post,默认是get.
go方法还可以指定http请求头\表单等数据
该方法原型
ok,reason=splash:go(url,baseurl=nil,headers=nil,http_method="GET",body=nil,formdata=nil)

参数说明:

  1. url:请求的url;
  2. baseurl:可选参数,默认为空,表示资源加载相对路径;
  3. headers:可选参数,默认为空,表示请求头;
  4. http_method:可选参数,默认为get,支持post
  5. body:可选参数,默认为空,post请求时的数据(字符串形式);
  6. formdata:可选参数,默认为空,post请求时的表单数据,在发送数据时,会将content-type请求头字段值设为application/x-www-form-urlencoded,而且会将post数据转换为urlencoded格式

例子:通过go函数使用post方法请求http://********/post,并返回HTML代码和Har图表

function main(splash, args)
	local ok,reason=splash:go{"http://**********g/post",http_method="POST",body="name=Bill"}
  if ok then
  	return {
      html=splash:html(),
      har=splash:har()
    }
    end
end

wait方法

该方法用于控制页面的等待时间,方法原型
ok,reason=splash:wait{time,cancel_on_redirect=false,cancel_on_error=true}

参数说明:

  1. time:等待的秒数
  2. cancel_on_redirect:可选参数,默认为false,表示如果发生了重定向就停止等待,并返回重定向结果
  3. cancel_on_error:可选参数,默认为false,表示如果发生了加载错误,就停止等待.
    返回结果统一是结果ok和原因reason的组合
function main(splash)
	splash:go("https://www.baidu.com")
  --等待5秒
  splash:wait(5)
  return splash:html()
end

这段代码等待5s后,返回百度首页的HTML代码

jsfunc方法

该方法用于直接调用JavaScript定义的函数,但所谓调用的JavaScript函数必须在一对双中括号内,相当于实现了JavaScript函数到Lua脚本的转换

例子:通过jsfunc方法调用一个JavaScript函数,该函数用于获取当前页面中a节点的总数

function main(splash, args)
  --调用JavaScript函数
  local get_a_count=splash:jsfunc([[
  function(){
    var body=document.body;
    var a_list=body.getElementsByTagName("a");
    return a_list.length;
  }
    ]])
  --加载完页面后会自动调用前面指定的JavaScript函数
  splash:go("https://www.jd.com")
--返回a节点的数据
  return ("these are is a node"):format(get_a_count())
end

evaljs方法

该方法可以执行JavaScript代码,并将最后一条JavaScript语句的结果返回

function main(splash, args)
  splash:go("https://www.jd.com")
  local title=splash:evaljs("document.title")
  return title
end

调用evaljs方法执行了document.title,这条JavaScript代码用于返回页面的标题

runjs方法

该方法可以执行JavaScript代码,功能与evaljs方法类似,但偏向于执行某些动作或者声明某些方法

function main(splash, args)
  --定义JavaScript函数get_name
  splash:runjs("get_name=function(){return 'Mike'}")
  --调用事先定义好的JavaScript函数get_name
  local name=splash:evaljs("get_name()")
  return name
end

输出Mike

autoload方法

该方法用于设置每个页面访问时自动加载的JavaScript代码,autoload方法原型
ok,reason=splash:autoload{source_or_url,source=nil,url=nil}

参数说明:

  1. source_or_url:JavaScript代码或JavaScript库链接
  2. source:JavaScript代码
  3. url:JavaScript库链接

但该方法只负责加载JavaScript代码或库,不执行任何操作,如果需要操作需要使用evaljs方法或者runjs方法

例子:使用autoload方法定义了2个JavaScript函数,通过evaljs函数调用了这两个JavaScript函数,然后使用autoload方法加载jQuery库,利用jQuery的API获取页面中a节点的总数

function main(splash, args)
	splash:autoload([[
    --获取页面标题
    function get_document_title(){
    	return document.title;
  }
    --获取页面中div节点的总数
    function get_div_count(){
    	var body=document.body;
    	var div_list=body.getElementsByTagName('div');
    	return div_list.length;
  }
    ]])
  --加载jQuery库
  splash:autoload{url="https://code.jquery.com/jquery-3.3.0.min.js"}
  splash:go("https://www.jd.com")
  --获取jQuery版本
  local version =splash:evaljs("$.fn.jquery")
  --获取页面中a节点的总数
  local a_count=splash:evaljs("$('a').length;")
  return {
    title=splash:evaljs("get_document_title()"),
    div_count=splash:evaljs("get_div_count()"),
    jquery_version=version,
    a_count=a_count
  }
end

call_later方法

该方法用于通过设置任务的延长时间实现任务延时执行,并执行前通过cancel方法重写执行定时任务

例子:使用call_later方法定义一个延迟任务,用于2秒后获取页面截图

function main(splash, args)
	local result={}
  splash:go("https://www.jd.com")
  splash:wait(0.5)
  result["png1"]=splash:png()
  --定义延时操作
  local timer=splash:call_later(function()
    result["png2"]=splash:png()
      end,2)--2是延时时间,单位秒
  splash:wait(3.0)
  return result
end

显示2个京东首页页面,如果把2改为3或者更大的数值,那么该页面只会显示1个京东商城首页截图,因为3秒后main方法退出,延时执行操作还没有执行

http_get方法

该方法可以模拟HTTP GET请求,原型:

response=splash:http_get{url,headers=nil,follow_redirects=true}

参数说明:

  1. url=请求的URL
  2. headers:可选参数,默认为空,请求头
  3. follow_redirects:可选参数,默认是true,表示是否开启自动重定向

例子:使用http_get方法发送一个HTTP GET请求,并输出返回结果和其他信息

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

http_post方法

与http_get方法类似,发送HTTP POST请求,多了一个body参数,原型:

response=splash:http_get{url,headers=nil,follow_redirects=true,body=nil}

参数说明:

  1. url=请求的URL
  2. headers:可选参数,默认为空,请求头
  3. follow_redirects:可选参数,默认是true,表示是否开启自动重定向
  4. body:可选参数,默认为空,表单数据

例子:使用http_post方法发送一个HTTP POST请求,并输出返回结果和其他信息

function main(splash, args)
  local treat=require("treat")
  local json=require("json")
  local response=splash:http_post{"http://httpbin.org/post",
  	body=json.encode({name="Mike",age=30,salary=1234.5}),
    headers={["content-type"]="application/json"}
  }
  return {
    html=treat.as_string(response.body),
    url=response.url,
    status=response.status
  }
end

set_content方法

用于设置网页内容

function main(splash, args)
  splash:set_content("<html><body><h1>hello world</h1></body></html>")
  return splash:png()
end

 

html方法

用于获取网页的源代码

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

png方法

用于获取png格式的页面截图

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

jpeg方法

与png方法类似,获取jpeg格式的页面截图

har方法

HAR,全称是HTTP Archive format(HTTP存档格式),是一种JSON格式的存档文件格式,多用于记录网页浏览器与网站的交互过程。文件扩展名通常为.har。HAR格式的规范定义了一个HTTP事务的存档格式,可用于网页浏览器导出加载网页时的详细性能数据

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

其他方法

1.url方法

获取当前正在访问的URL

2.get_cookies方法

获取当前页面的cookies

3.add_cookie方法

该方法用于为当前页面添加cookie,原型:

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

add_cookie方法的参数代表cookie的各个参数

function main(splash, args)
  splash:add_cookie{"name","Mike","/",domain="http://example.com"}
	splash:go("http://example.com")
  return splash:get_cookies()
end

4.clear_cookie方法

清除所有cookies

5.get_viewport_size方法

获取当前浏览器页面的尺寸,宽度高度

6.set_viewport_size方法

设置当前浏览器页面的尺寸,宽度高度,原型:

splash:set_viewport_size(width,height)

function main(splash, args)
    splash:set_viewport_size(400,800)
    splash:go("https://www.jd.com")
    return splash:png()
end

7.set_viewport_full方法

设置浏览器全屏显示

8.set_user_agent方法

设置浏览器的user-agent

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

9.set_custom_headers方法

该方法用于设置请求头

function main(splash, args)
  splash:set_custom_headers({
      ["User-Agent"]="test agent",
      ["Custom-Header"]="Value"
    })
	splash:go("http://httpbin.org/get")
  return splash:html()
end

CSS选择器

select方法

该方法用于查找第1个符合条件的节点。如果多个节点符合条件,只会返回第1个符合条件的节点。select方法的参数时CSS选择器

例子:使用select方法查找京东商城首页搜索框节点,并输入搜索关键字

function main(splash, args)
	splash:go("https://www.jd.com")
  --查找id属性值为key的节点
  input=splash:select("#key")
  --在搜索框中输出“python从菜鸟到高手”
  input:send_text("python从菜鸟到高手")
  splash:wait(2)
  return splash:png()
end

select_all方法

查找所有符合条件的节点

例子:使用select_all方法查找京东商城首页所有名为a的节点,并返回a节点的文本内容和href属性值

function main(splash, args)
  local treat=require("treat")
  splash:go("https://www.jd.com")
  splash:wait(0.5)
  --查找页面所有的a节点
  local a_list=splash:select_all('a')
  local results={}
  --对所有的a节点进行迭代,得到每一个a节点的文本和href属性
  for index,a in ipairs(a_list) do
    results[index]={text=a.node.innerHTML,href=a.node.attributes.href}
    end
  return treat.as_array(results)
end

 模拟鼠标与键盘动作

例子:send_text方法在京东商城搜索文本框中输入关键字,然后使用mouse_click方法模拟单击搜索按钮动作,send_keys("<Return>")代表回车键

function main(splash)
    splash:go("https://www.jd.com")
    input = splash:select("#key")
    input:send_text("Python从菜鸟到高手")
    button = splash:select("#search > div > div.form > button")
    -- 单击搜索按钮
    button:mouse_click()
    splash:wait(1)
    return splash:png()
end
function main(splash, args)
    splash:go("https://www.jd.com")
    input=splash:select("#key")
    input:send_text("python从菜鸟到高手")
    --回车
    input:send_keys("<Return>")
    splash:wait(1)
    return splash:png()
end

Splash HTTP API

Splash HTTP API是splash提供的一组URL,通过为这些URL指定各种参数,完成对页面的各种渲染工作

1.render.html

该接口用于获取JavaScript渲染的页面的HTML代码,接口的URL如下

http://localhost:8050/render.html

这个接口可以接收一个名为url的参数,用于指定待渲染页面的地址,可用curl命令测试这个接口

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

在终端执行上面的代码,会返回首页的代码

python调用:

wait参数,得到响应的时间会变长,wait参数值设为3,表示3秒后,才会获取京东商城首页代码

import requests
url="http://localhost:8050/render.html?url=https://www.jd.com&wait=3"
response=requests.get(url)
print(response.text)

2.render.png

接口可以获取网页截图,参数比render.html多了几个,由于获取的是截图,所以需要指定截图的宽度和高度。两个值分别由width和height设置。有curl命令测试:

curl http://localhost:8050/render.png?url=https://www.jd.com --output jd.png

import requests
url="http://localhost:8050/render.png?url=https://www.jd.com&wait=3&width=800&height=500"
response=requests.get(url)
with open("jd.png",'wb') as f:
    f.write(response.content)

返回并保存一个800 x 500尺寸的png格式的图像

3.render.jpeg

用法与render.png类似,只不过返回的是jpeg格式的二进制数据,比render.png多了参数quality,用来设置图片的质量

4.render.har

curl命令测试类似

import requests
url="http://localhost:8050/render.har?url=https://www.jd.com&wait=3"
response=requests.get(url)
print(response.text)

5.render.json

该接口包含前面介绍的接口的全部功能,如获取HTML代码,HAR数据,PNG格式截图等

如果render.json接口不加任何参数,默认以JSON格式返回请求URL,页面标题,页面尺寸等信息

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

如果要同时获取HTML代码,HAR数据和PNG截图,可以分别将html,har,png参数值设为1

curl http://localhost:8050/render.json?url=https://httpbin.org&html=1&har=1&png=1

如果返回的信息包含二进制数据,会以Base64编码形式返回这些二进制数据,如获取PNG格式的页面截图,会作为JSON对象的png属性返回PNG图像数据

6.execute

该接口的功能十分强大。前面介绍的所有接口只能通过URL的参数实现特定的一些功能,而通过execute接口,可以实现Python与Lua对接,相当于Python代码中直接执行Lua脚本

通过execute接口的lua_source参数,可以指定一段Lua脚本,然后交由Splash执行,执行完后,会返回执行结果返回给python

例子:通过execute接口执行2段Lua脚本,第1段Lua脚本返回一个简单的字符串,第2段Lua脚本访问https://*****.com,然后将PNG格式的截图返回给Python,并保存名为weather.png的图像文件

import requests
from urllib.parse import quote
lua="""
function main(splash)
    return "世界 你好"
end
"""
url="http://localhost:8050/execute?lua_source="+quote(lua)
response=requests.get(url)
print(response.text)

lua="""
function main(splash)
    splash:go("https://weather.com")
    splash:wait(3)
    return {
        html=splash:html(),
        png=splash:png()
    }
end
"""
url="http://localhost:8050/execute?lua_source="+quote(lua)
response=requests.get(url)

import json
import base64
# 将返回的JSON格式的数据转换为JSON对象
json_obj=json.loads(response.text)
# 获取Base64格式的图像文件数据
png_base64=json_obj['png']
png_bytes=base64.b64decode(png_base64)
# 将截图保存为weather.png文件
with open('weather.png','wb') as f:
    f.write(png_bytes)

执行完后返回
世界 你好和一个名为weather.png的文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值