python chrome headless_[技巧] chrome headless 爬虫抓取websoket 数据
目录
源起
分析
实践
总结
源起
周末答应了一个朋友帮他看一下一个网站应该怎么爬,费话不说直接先上网站
https://datacenter.jin10.com/price
数据一直在不停的闪,直觉判断这种高频的显示应该不会用ajax 轮询的方式,至少也是websocket的方式
分析
老规矩,直接上chrome 的f12来分析看看
直接看到,右边正边疯狂的刷新数据,而使用的协议,正是websocket ,对于python下如何连接websocket ,网上有很多的文章,我这里就不用细说了,通常我们拿到这样的接口,都会本能去尝试直连看看,在进一步尝试之后,发现他们的api应该有一种特别的方式(又或者我的代码有写错的地方)
# coding:utf-8
from websocket import create_connection
from websocket import ABNF
api = "wss://sshibikfdn.jin10.com:9084/socket.io/?EIO=3&transport=websocket&sid=VsJvZikGdc8spBaPAAMO"
headers = {
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Cookie': 'UM_distinctid=16614315bf179b-0354a40c6714ff-34677908-232800-16614315bf2acb; XSRF-TOKEN=eyJpdiI6IkNZRU9uSmM1ZnY2M0VqNUttK1pxRGc9PSIsInZhbHVlIjoiRlJpNlRuekIxTDJZeVd3bHpvXC9OUEZGamw4VndZNEdXTEVsRjRMaFFyOEIxUHRtNDdTc1JaQ042eG4xdjlFeWJjWGlkcWFaeWl6NTRVUUlQMThaZmJ3PT0iLCJtYWMiOiJkYWU1MzQ2NjEyM2U3OTk0MzY5NWNjZTdhZmNlZjE0YTViMjc2YzBiYWM4YjhiMjNhZmRjMzU3YzliNDg3ZGIzIn0%3D; laravel_session=eyJpdiI6IjBRS3h0Y29XcGRBRlFIc0xIeWFiZGc9PSIsInZhbHVlIjoibVRLblpNTDJJa1JIN1ZJc0s5c2xrSkYzckNadDB6aGp0REd5SVJQTlkxNVAzajhvdXY5ZElSQ3VTcGVicjNiSXZ3NE9pZDZOdHJUM1d6WG1KQjZXNkE9PSIsIm1hYyI6Ijg3MWVkZDVlMDFjZDM2NDRjZmI2ZDhkNDJmZGI5MjNhMzk3MTViNmI1YTNmMDRmYWJjNzQ4ZGU2YWZhNzNhNzUifQ%3D%3D; io=VsJvZikGdc8spBaPAAMO',
'Host': 'sshibikfdn.jin10.com:9084',
'Connection': 'Upgrade',
'Origin': 'https://datacenter.jin10.com',
'Pragma': 'no-cache',
'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
'Sec-WebSocket-Key': 'g4UA3smEJ0eGufMkyz7AOw==',
'Sec-WebSocket-Version': '13',
'Upgrade': 'websocket',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
def get_web_socket():
start_message = "2probe"
ws = create_connection(
api,
header=headers,
cookie=headers['Cookie'],
#origin=headers['Origin'],
#host=headers['Host']
)
frame = ABNF.create_frame("2probe", ABNF.OPCODE_TEXT)
ws.send_frame(frame)
data = ws.recv_frame()
print(data)
if __name__ == '__main__':
get_web_socket()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# coding:utf-8
fromwebsocketimportcreate_connection
fromwebsocketimportABNF
api="wss://sshibikfdn.jin10.com:9084/socket.io/?EIO=3&transport=websocket&sid=VsJvZikGdc8spBaPAAMO"
headers={
'Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8',
'Cookie':'UM_distinctid=16614315bf179b-0354a40c6714ff-34677908-232800-16614315bf2acb; XSRF-TOKEN=eyJpdiI6IkNZRU9uSmM1ZnY2M0VqNUttK1pxRGc9PSIsInZhbHVlIjoiRlJpNlRuekIxTDJZeVd3bHpvXC9OUEZGamw4VndZNEdXTEVsRjRMaFFyOEIxUHRtNDdTc1JaQ042eG4xdjlFeWJjWGlkcWFaeWl6NTRVUUlQMThaZmJ3PT0iLCJtYWMiOiJkYWU1MzQ2NjEyM2U3OTk0MzY5NWNjZTdhZmNlZjE0YTViMjc2YzBiYWM4YjhiMjNhZmRjMzU3YzliNDg3ZGIzIn0%3D; laravel_session=eyJpdiI6IjBRS3h0Y29XcGRBRlFIc0xIeWFiZGc9PSIsInZhbHVlIjoibVRLblpNTDJJa1JIN1ZJc0s5c2xrSkYzckNadDB6aGp0REd5SVJQTlkxNVAzajhvdXY5ZElSQ3VTcGVicjNiSXZ3NE9pZDZOdHJUM1d6WG1KQjZXNkE9PSIsIm1hYyI6Ijg3MWVkZDVlMDFjZDM2NDRjZmI2ZDhkNDJmZGI5MjNhMzk3MTViNmI1YTNmMDRmYWJjNzQ4ZGU2YWZhNzNhNzUifQ%3D%3D; io=VsJvZikGdc8spBaPAAMO',
'Host':'sshibikfdn.jin10.com:9084',
'Connection':'Upgrade',
'Origin':'https://datacenter.jin10.com',
'Pragma':'no-cache',
'Sec-WebSocket-Extensions':'permessage-deflate; client_max_window_bits',
'Sec-WebSocket-Key':'g4UA3smEJ0eGufMkyz7AOw==',
'Sec-WebSocket-Version':'13',
'Upgrade':'websocket',
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
defget_web_socket():
start_message="2probe"
ws=create_connection(
api,
header=headers,
cookie=headers['Cookie'],
#origin=headers['Origin'],
#host=headers['Host']
)
frame=ABNF.create_frame("2probe",ABNF.OPCODE_TEXT)
ws.send_frame(frame)
data=ws.recv_frame()
print(data)
if__name__=='__main__':
get_web_socket()
在运行程序之后毫无效果,另外端口的api会根据真实的请求变化 ,而且进一步的请求的cookie和key都会变化 ,看来直连的方式是行不通了,那没办法,只能走渲染的路了,selenium ? 可以是可以,不过我们要尝试一下新的路线和方法,那就直接上chrome-headless
实践
Headless Chrome指在headless模式下运行谷歌浏览器(以程序模式运行,没有界面),自从这玩意儿出来之后, phantomjs的作者就宣布甩锅不维护了(人家也确实辛苦,没啥收益),可以说是一个非常好的工具了,咱们说干就干
安装
直接使用docker 来安装chrome headless
docker run -d -p 9222:9222 --cap-add=SYS_ADMIN justinribeiro/chrome-headless
1
2
dockerrun-d-p9222:9222--cap-add=SYS_ADMINjustinribeiro/chrome-headless
环境
python 3.6
ubuntu16.04
pip install websocket-client
pip install requests
1
2
3
pipinstallwebsocket-client
pipinstallrequests
编码
这样我们已经启用了一个chrome headless的服务,那如何使用呢,我们使用websocket 和chrome header less进行交互,不多说了,直接上代码吧
import json
import time
import requests
import websocket
request_id = 0
target_url = 'https://datacenter.jin10.com/price'
def get_websocket_connection():
r = requests.get('http://10.10.2.42:9222/json') #这是开启docker chrome headless的机器地址
if r.status_code != 200:
raise ValueError("can not get the api ,please check if docker is ready")
conn_api = r.json()[0].get('webSocketDebuggerUrl')
return websocket.create_connection(conn_api)
def run_command(conn, method, **kwargs):
global request_id
request_id += 1
command = {'method': method,
'id': request_id,
'params': kwargs}
conn.send(json.dumps(command))
#while True:
msg = json.loads(conn.recv())
if msg.get('id') == request_id:
return msg
def get_element():
conn = get_websocket_connection()
msg = run_command(conn, 'Page.navigate', url=target_url)
time.sleep(5)
js = "var p = document.querySelector('.jin-pricewall_list-item_b').innerText ; p ;"
for _ in range(20):
time.sleep(1)
msg = run_command(conn, 'Runtime.evaluate', expression=js)
print(msg.get('result')['result']['value'])
if __name__ == '__main__':
get_element()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
importjson
importtime
importrequests
importwebsocket
request_id=0
target_url='https://datacenter.jin10.com/price'
defget_websocket_connection():
r=requests.get('http://10.10.2.42:9222/json')#这是开启docker chrome headless的机器地址
ifr.status_code!=200:
raiseValueError("can not get the api ,please check if docker is ready")
conn_api=r.json()[0].get('webSocketDebuggerUrl')
returnwebsocket.create_connection(conn_api)
defrun_command(conn,method,**kwargs):
globalrequest_id
request_id+=1
command={'method':method,
'id':request_id,
'params':kwargs}
conn.send(json.dumps(command))
#while True:
msg=json.loads(conn.recv())
ifmsg.get('id')==request_id:
returnmsg
defget_element():
conn=get_websocket_connection()
msg=run_command(conn,'Page.navigate',url=target_url)
time.sleep(5)
js="var p = document.querySelector('.jin-pricewall_list-item_b').innerText ; p ;"
for_inrange(20):
time.sleep(1)
msg=run_command(conn,'Runtime.evaluate',expression=js)
print(msg.get('result')['result']['value'])
if__name__=='__main__':
get_element()
整体逻辑非常简单,打开指定页面,等待页面数据刷新,然后直接偷懒拿数据渲染之后的页面值,运行效果如下:
其中的0 是因为页面还在渲染之中,所以数据还没有正式的出现在前台界面上
总结
本次主要使用了chrome-headless的相关渲染环境来解决了我们抓取数据的问题,并且使用了websocket api 来进一步操作,其实google 官方有sdk进行操作,https://github.com/GoogleChrome/puppeteer ,渲染的终究不是高效的做法,但是对于这种单页面目的性很强的数据,可以尝试渲染大法
python chrome headless_[技巧] chrome headless 爬虫抓取websoket 数据相关推荐
- 如何用python爬股票数据_python爬虫股票数据,如何用python 爬虫抓取金融数据
Q1:如何用python 爬虫抓取金融数据 获取数据是数据分析中必不可少的一部分,而网络爬虫是是获取数据的一个重要渠道之一.鉴于此,我拾起了Python这把利器,开启了网络爬虫之路. 本篇使用的版本为 ...
- python3 爬虫抓取股市数据
python3 爬虫抓取股市数据 爬虫抓取数据的一般步骤 代码 运行结果 小结 注意事项 爬虫抓取数据的一般步骤 1.确定需要抓取的网站2.分析url,找到url的的变化规律3.分析页面的数据4.获取 ...
- 爬虫抓取页面数据原理(php爬虫框架有很多 )
爬虫抓取页面数据原理(php爬虫框架有很多 ) 一.总结 1.php爬虫框架有很多,包括很多傻瓜式的软件 2.照以前写过java爬虫的例子来看,真的非常简单,就是一个获取网页数据的类或者方法(这里的话 ...
- 爬虫抓取网络数据时经常遇到的六种问题
随着互联网时代的不断发展,爬虫采集已经成为了目前最为主流的数据获取方式.使用爬虫软件自动从网站中提取数据可以节省大量的时间和精力.但是,如果网站所有者发现了用户的真实IP地址,往往就会直接选择进行限制 ...
- node爬虫,抓取网页数据
node爬虫,抓取网页数据 1.什么是爬虫? 抓取信息或者数据的程序或者是脚本 2.通过node实现对网页数据的抓取. 安装插件 request,处理请求(此包以被弃用) npm i request ...
- Python爬虫抓取动态数据
一个月前实习导师布置任务说通过网络爬虫获取深圳市气象局发布的降雨数据,网页如下: 心想,爬虫不太难的,当年跟zjb爬煎蛋网无(mei)聊(zi)图的时候,多么清高.由于接受任务后的一个月考试加作业一大 ...
- Python判断股票是交易日,爬虫抓取深交所交易日历
为了判断某一天是不是股票的交易日,以此区分自然日与交易日,我们通过抓取深交所的交易日历获取相关数据 获取交易日思路 首先,打开深交所的交易日历页面:http://www.szse.cn/aboutus ...
- python和人工智能爬虫_Python 演示人工智能爬虫 抓取新浪微博数据
时间:2019-04-10 概述:搜索爬虫 人工智能 一个Python 人工智能爬虫演示,本代码演示抓取新浪微博数据,若正在采集新浪微博数据,如需取消请按CTRL+C 退出程序. #!/usr/bin ...
- java爬虫抓取网页数据论坛_Java爬虫抓取网页
Java爬虫抓取网页原作者:hebedich 原文链接 下面直接贴代码: import java.io.BufferedReader; import java.io.InputStreamReade ...
最新文章
- ubuntu 使用ccache加快linux内核编译速度
- placeholder的兼容处理(jQuery下)
- 可以公开访问的 SAP gateway demo system ES5/002
- 往ABAP gateway system上和Cloud Foundry上部署HTML5应用
- 7 种分布式全局 ID 生成策略,你更爱哪种?
- 信息学奥赛一本通 1397:简单算术表达式求值 | OpenJudge NOI 1.12 01:简单算术表达式求值
- 去哪儿-07-city-router
- [Java] 蓝桥杯ADV-203 算法提高 8皇后·改
- 程序员听爵士,架构师学做交响指挥
- STM8L152C6T6+IAP详解,包教包会
- 用电脑计算器计算以2为底的对数
- 视频 | 计算万物的理论
- 用计算机编纂家谱的作用,家谱的编纂几大流程?
- 爱尔兰房产泡沫破灭带给我们…
- 黑客长期摇号不中黑掉北京小客车摇号网
- VUE3(二十四)自定义alert弹窗组件
- 安卓卡片式ViewPager
- 面试西装的颜色、款式、质地的搭配
- 从浏览器下载表格数据为Excel的两种实现方法
- [后台系统模板]优质、整洁的基于Bootstrap 3 Bootstrap 4的响应式后台管理系统模板...