Splash简介及安装方法 使用Splash抓取网页动态数据

首页 » Python » Splash简介及安装方法 使用Splash抓取网页动态数据

Splash是一个针对js渲染服务,它内置了一个浏览器窗口,基于Python3和Twisted引擎,所以可以异步处理任务。由于我的电脑是win7,所以这只介绍win7上splash的安装和使用

Splash简介及安装

Splash具有JavaScripts渲染功能并带有HTTP API的轻量级浏览器,同时还对接了Python的网络引擎框架Twisted和QT库,让服务具有异步处理的能力,以发挥webkit的并发能力。简单来说,Splash是一个带有API接口的轻量级浏览器,使用它提供的API接口可以简单实现Ajax动态数据的抓取。

Splash的安装是基于Docker应用容器引擎,Docker支持三大操作系统:Linux、MacOS和Windows。首先需要安装docker。docker是基于Go语言实现开发的开源容器项目,诞生于2013年,所谓容器,可以简单的理解为隔断,或者是桶装方便面。那么安装可参考:Docker容器的安装以及常见错误 这里不再详细介绍!建议先去看一下,安装阿里云的镜像,不然你安装不了任何的东西!

通过Docker安装Scrapinghub/splash镜像,然后启动容器,创建splash服务,在$后面输入以下代码(不能直接粘贴,可以在工具的顶端右击.编辑–粘贴):

docker pull scrapinghub/splash

等待所有的结果都为Pull complete就可以了,可能会卡住,你关掉重启删除镜像,重现安装。 必须要配制镜像加速,不然成功不了!

docker run -p 8050:8050 -p 5023:5023 scrapinghub/splash
#通过浏览器访问8050端口验证安装是否成功

如果成功会一直卡再呢里!如果失败删掉镜像重新pull即可!注意需要配置镜像加速,不然玩不了,可参考:Docker容器的安装以及常见错误

访问本地:http://localhost:8050,进入本地的splash,如果出现无法访问的话,在启动docker的时候出现有鲸鱼的图标,左下角显示的是IP:

Splash简介及安装方法 使用Splash抓取网页动态数据

我们可以访问:http://192.168.99.100:8050/。当然直接访问就可以了,或者你想查看一下IP:

docker-machine ip default

如果你在网页中看到了下图,那么恭喜你成功了!也是废了不少时间呐!

Splash简介及安装方法 使用Splash抓取网页动态数据

对于其中的代码这里不做太详细的介绍,请忽略掉!

使用Splash的API接口

Spalsh最大的作用是可以执行JavaScript代码,将Ajax动态数据直接加在到网页上,无需开发者花费时间和精力分析Ajax请求,从而实现相关数据的抓取。

Python可以使用Splash提供的API接口从而实现Python与Splash之间的交互。Splash提供多种API接口实现不同的功能。当然首先需要在Python中安装scrappy-splash:pip install scrappy-splash

我们需要重点看的就是渲染render mel得到render.html。这里以百度为例,修改render mel的地址栏为:https://www.baidu.com/,然后点击render me,之后你会看到下图:

Splash简介及安装方法 使用Splash抓取网页动态数据

我们抓取网页的,你知道重点在哪里了吧!红箭头的位置就是我们爬虫该看的东西:html: String,它相当于把百度的首页从js层面做了渲染。har: HAR data是网页请求过程中的一些信息,这里网速原因没有显示出来。 png: Image是截图网页的图片。

那么我们复制网页中的url地址:

http://192.168.99.100:8050/info?wait=0.5&images=1&expand=1&timeout=90.0&url=https%3A%2F%2Fwww.baidu.com%2F&lua_source=function+main%28splash%2C+args%29%0D%0A++assert%28splash%3Ago%28args.url%29%29%0D%0A++assert%28splash%3Await%280.5%29%29%0D%0A++return+%7B%0D%0A++++html+%3D+splash%3Ahtml%28%29%2C%0D%0A++++png+%3D+splash%3Apng%28%29%2C%0D%0A++++har+%3D+splash%3Ahar%28%29%2C%0D%0A++%7D%0D%0Aend

我们可以注意到url的参数很多,其中url必填,timeout(超时时间)和wait(页面加载完毕后等待的时间)选填。也就是通过这种方式,我们就可以得到js渲染后的页面,使用下面的url当然也可以:

http://192.168.99.100:8050/render.html?url=http://www.baidu.com/&timeout=30&wait=0.5

Splash实战操作

今日头条

今日头条的首页是采用js渲染,你查看源代码只能看到一些js代码,网页中的新闻是不存在的,那么我们按照上面的url来进行演示,这个就是splash提供的一个接口,我们通过这个接口就可得到js渲染后的页面,那么今日头条首页:https://www.toutiao.com/,只是没有渲染过的页面,你自己尝试一下两者的效果,这里只演示如何使用js渲染,代码参考:

import requests
from lxml import etree
#url='https://www.toutiao.com/'
#使用splash的url
url='http://192.168.99.100:8050/render.html?url=https://www.toutiao.com/&timeout=30&wait=0.5'
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0'}
resposne=requests.get(url,headers=headers)
# print(resposne.text)
tree=etree.HTML(resposne.text)
title=tree.xpath('//div[@class="title-box"]/a/text()')
print(title)

这是一种最简单的演示方式,你可以在浏览器输入代码中的url,可以看到的也是今日头条的首页,只不过它是js渲染后的页面,我们就可以通过简单的xpath来提取标题,由于是演示,代码非常的不规范,需要自己修改尝试,抛砖引玉哈哈!

豆瓣电影

豆瓣电影的首页也是通过js渲染生成的,在首页的源代码中是找不到任何电影名字的字段的,我们来试一下,其实你可以在浏览器中输入splash的url,我们看到的还是豆瓣的首页(图片不显示,没影响吧!),只不过我们在源代码中可以找到所有的电影信息,代码参考:

import csv
import requests
from lxml import etree
fw=open('douban.csv','w',encoding='utf-8')
fieldname = ['moves_title', 'move_score']
writer = csv.writer(fw)
writer.writerow(fieldname)

url='http://192.168.99.100:8050/render.html?url=https://movie.douban.com/&timeout=30&wait=0.5'
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0'}
resposne=requests.get(url,headers=headers)
# print(resposne.text)
tree=etree.HTML(resposne.text)
#提取包含每个电影的大分类
div_list=tree.xpath('//div[@class="slide-wrapper"]/div[@class="slide-page"]//a')
for div in div_list: #遍历
    item={}

    #存在换行符,所以使用这种方式替换掉
    #换行符strip为0,所以我们判断一下
    item['title']=[title.strip() for title in div.xpath('./p/text()') if len(title.strip())>0][0]
    item['score']=[score.strip() for score in div.xpath('./p/strong/text()') if len(score.strip())>0][0]
    writer.writerow([item['title'],item['score']])


代码如果又不理解的地方就是列表生成式没掌握,可移至:Python的列表

splash自定义lua脚本

我们可以看到下图中的代码,其实我们也可以自定义脚本的,我们可以定义一个hello world的脚本来试一试!

Splash简介及安装方法 使用Splash抓取网页动态数据

import requests
from urllib.parse import quote
lua='''
function main(splash)
    return 'hello world'
end
'''
url='http://192.168.99.100:8050/execute?lua_source='+quote(lua)
response=requests.get(url)
print(response.text)

执行以上代码就会返回hello world。那么我们在看一下自定义百度的脚本:

import requests
from urllib.parse import quote
lua='''
function main(splash,args)
    local treat=require("treat")
    local response=splash:http_get("http://www.baidu.com")
        return{
            html=treat.as_string(response.body),
            url=response.url,
            status=response.status
            }
end
'''

url='http://192.168.99.100:8050/execute?lua_source='+quote(lua)
response=requests.get(url)
print(response.text)

返回的html就是js渲染过后的网页,我没有写注释,因为这是一种固定的写法。具体的使用方法就是替换http_get的值,非常简单!

使用方法总结

import requests
headers={
    "User-Agent":"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
}
base_url="" # JS加载的网页url
# render.html 获取JS加载后的网页信息
url='http://192.168.99.100:8050/render.html?url='+base_url+'&wait=5'
response=requests.get(url,headers=headers)
print(response.text)
——————————————————————————————
# render.png 获取网页截图
url='http://192.168.99.100:8050/render.png?url='+base_url+'&waidth=500&height=500'
response=requests.get(url,headers=headers)
with open('./img.png','wb') as f:
    f.write(response.content)
——————————————————————————————
# render.json 返回请求数据
url='http://192.168.99.100:8050/render.json?url='+base_url+'&wait=5'
response=requests.get(url,headers=headers)
print(response.text)
——————————————————————————————
# execute执行Lua脚本 Splash支持lua脚本
from urllib.parse import quote
luaScript='''
function main(splash)
    return 'hello world'
end
'''
# Lua脚本转码处理
url='http://192.168.99.100:8050/execute?lua_source='+quote(luaScript)
response=requests.get(url)
print(response.text)

Lua脚本常用对象方法

1、go()方法:该方法对某个链接发送HTTP请求,模拟GET和POST请求

# Lua脚本
function main(aplash,args)
   local ok,reason=splash:go("http://httpbin.org/post",
         http_method="POST",body="name=eyujun")
   if ok then
       return splash:html()
end
参数解释:
url:请求的url
baseurl:可选参数,默认空,表示资源加载相对路径
headers:可选参数,默认空,表示请求头
http_method:可选参数,默认为GET,支持POST请求
body:可选参数,默认为空,发送POST请求的表单数据,数据以JSON格式表示
formdata:可选参数,默认空,发POST请求的表单数据

该方法返回ok和reason前者是返回请求结果,后者是返回HTTP的状态码。若ok为空则说明网页加载的时候出错,reason惠济路相应的错误信息,反之则说明网页加载成功。

2、wait():该方法用于控制网页加载等待时间

# Lua脚本
function main(splash,args)
    splash:go("http://httpbin.org")
    splash:wait(5)
    return {
       html=splash:html() 
   }
end
参数解释:
time:等待的秒数
cancel_onredirect:可选参数,默认false,表示发生重定向就停止等待,并返回重定向结果
cancel_on_error:可选参数,默认false,表示发生了加载做粗就停止等待。

3、http_get():该方法用于模拟发送HTTP的GET请求

# Lua脚本
function main(splash,args)
    local treat=require("treat")
    local response=splash:http_get("http://www.baidu.com")
        return{
            html=treat.as_string(response.body),
            url=response.url,
            status=response.status
            }
end
参数解释:
url:请求的url地址
headers:可选参数,默认空,设置请求头
follow_redirects:可选参数,是否启动自动重定向

4、http_post():该方法用于模拟发送HTTP的POST请求

# Lua脚本
function main(splash,args)
    local treat=require("treat")
    local response=splash:http_post("http://httpbin.org",body="name=eyujun")
        return{
            html=treat.as_string(response.body),
            url=response.url,
            status=response.status
            }
end
参数解释:
url:请求的url
headers:可选参数,默认空,设置请求头
follow_redirects:可选参数,是否启动自动重定向
body:可选参数,默认空

5、get_cookies():该方法用于获取当前页面的Cookies

# Lua脚本
function splash(main,args)
    # 如果有多条Cookies,则使用多次add_cookies()添加
    splash:add_cookies("name","eyuju")
    splash:go("https://www.e1yu.com")
    return splash:html()
end
参数解释:
name:当前Cookies的名称
value:当前Cookies的数值
path:可选参数,默认空,代表Cookies所在的目录
domain:可选参数,默认空,代表Cookies所在的域
expires:可选参数,默认空,表示Cookies的有效期
httpOnly:可选参数,默认空,设置Cookies是否支持JS读取
secure:可选参数,默认空,设置Cookies的跨域传递等安全问题

6、set_custom_headers():该方法用于设置请求头

# Lua脚本
function main(splash)
    splash:set_custom_headers({
        ["User-Agent"]:"Splash",
        ["Referer"]:"http://www.e1yu.com/"
        })
    splash:go("http://httpbin.org/")
    return {
       splash:html()
    }

更多介绍可参考Splash官方文档

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《Splash简介及安装方法 使用Splash抓取网页动态数据》 发布于2020-02-23

分享到:
赞(1) 赏杯咖啡

评论 抢沙发

7 + 5 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册