很多页面上会有一些websocket动态数据,这些数据一般每过N秒会自动刷新数据,并在页面上进行闪烁数据。最明显的示例就是行情类数据。这里选取目标站点:https://datacenter.jin10.com/price 。

websocket-price
websocket-price

这里还是使用Headless Chrome模式进行抓取,不过这次换种玩法,不和selenium进行结合了。这里使用docker运行一个chrome实例。

1docker run -d -p 9222:9222 --cap-add=SYS_ADMIN justinribeiro/chrome-headless

联网状态下,如果没有该镜像会从docker官方镜像站进行下载,下载成功后再运行,不过由于网络的原因,该image下载会比较慢,可以考虑换用国内源或者直接就放在后台,晚上让它跑。这里使用的环境是python3.7,安装相关模块的命令如下:

1pip install websocket-client
2pip install requests

这样我们已经启用了一个chrome headless的服务,接下来使用websocket 和chrome headless进行交互,代码如下:

 1import json
 2import time
 3import requests
 4import websocket
 5request_id = 0
 6target_url = 'https://datacenter.jin10.com/price'
 7def get_websocket_connection():
 8    r = requests.get('http://10.10.2.42:9222/json') #这是开启docker chrome headless的机器地址
 9    if r.status_code != 200:
10        raise ValueError("can not get the api ,please check if docker is ready")
11    conn_api = r.json()[0].get('webSocketDebuggerUrl')
12    return websocket.create_connection(conn_api)
13def run_command(conn, method, **kwargs):
14    global request_id
15    request_id += 1
16    command = {'method': method,
17               'id': request_id,
18               'params': kwargs}
19    conn.send(json.dumps(command))
20    #while True:
21    msg = json.loads(conn.recv())
22    if msg.get('id') == request_id:
23        return msg
24def get_element():
25    conn = get_websocket_connection()
26    msg = run_command(conn, 'Page.navigate', url=target_url)
27    time.sleep(5)
28    js = "var p = document.querySelector('.jin-pricewall_list-item_b').innerText ; p ;"
29    for _ in range(20):
30        time.sleep(1)
31        msg = run_command(conn, 'Runtime.evaluate', expression=js)
32        print(msg.get('result')['result']['value'])
33if __name__ == '__main__':
34    get_element()

整体逻辑非常简单,打开指定页面,等待页面数据刷新,然后直接偷懒拿数据渲染之后的页面值。