很多页面上会有一些websocket动态数据,这些数据一般每过N秒会自动刷新数据,并在页面上进行闪烁数据。最明显的示例就是行情类数据。这里选取目标站点:https://datacenter.jin10.com/price 。
这里还是使用Headless Chrome模式进行抓取,不过这次换种玩法,不和selenium进行结合了。这里使用docker运行一个chrome实例。
docker run -d -p 9222:9222 --cap-add=SYS_ADMIN justinribeiro/chrome-headless
联网状态下,如果没有该镜像会从docker官方镜像站进行下载,下载成功后再运行,不过由于网络的原因,该image下载会比较慢,可以考虑换用国内源或者直接就放在后台,晚上让它跑。这里使用的环境是python3.7,安装相关模块的命令如下:
pip install websocket-client pip install requests
这样我们已经启用了一个chrome headless的服务,接下来使用websocket 和chrome headless进行交互,代码如下:
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()
整体逻辑非常简单,打开指定页面,等待页面数据刷新,然后直接偷懒拿数据渲染之后的页面值。