Python中如何使用Google Chrome Dev Protocol操作Chrome/Headless Chrome?
项目地址: fate0/pychrome
用处:
直接使用 Google Chrome Dev Protocol 操作 chrome/headless chrome,比较灵活(前提要过一遍 Protocol) 。 更多信息请看 README.md
为什么要写:
想使用 headless chrome 来替换 PhantomJS 作爬虫,我找了一下,Python 好像并没有和 chrome-remote-interface 一样直接使用 Chrome DevTools Protocol 来操作 chrome 的 Package,后面就自己写了一个。
最后:
欢迎各种 star、issue 以及 pr (。・`ω´・)
Python中如何使用Google Chrome Dev Protocol操作Chrome/Headless Chrome?
和 selenium 的区别是???
要操作Chrome/Headless Chrome,直接用 selenium 或者 playwright 更省事。不过你点名要CDP(Chrome DevTools Protocol),那得用 websockets 或者 pychrome 这类库直接和浏览器对话。
这里给你个最直接的例子,用 websockets 连上CDP,让浏览器打开个页面然后截图。首先确保装了 websockets 库:pip install websockets。
import asyncio
import websockets
import json
async def control_chrome():
# 先手动启动Chrome,打开调试端口
# 命令大概是:chrome --remote-debugging-port=9222 --headless
# 这里假设你已经开了一个Chrome实例在9222端口
async with websockets.connect('ws://localhost:9222/devtools/browser/') as ws:
# 1. 创建新标签页
create_target = {
"id": 1,
"method": "Target.createTarget",
"params": {"url": "about:blank"}
}
await ws.send(json.dumps(create_target))
response = await ws.recv()
target_id = json.loads(response)['result']['targetId']
# 2. 附加到该标签页
attach_target = {
"id": 2,
"method": "Target.attachToTarget",
"params": {"targetId": target_id, "flatten": True}
}
await ws.send(json.dumps(attach_target))
response = await ws.recv()
session_id = json.loads(response)['result']['sessionId']
# 3. 导航到网页
navigate = {
"id": 3,
"method": "Page.navigate",
"params": {"url": "https://www.example.com"},
"sessionId": session_id
}
await ws.send(json.dumps(navigate))
await ws.recv() # 等待导航完成
# 4. 等页面加载
await asyncio.sleep(2)
# 5. 截图
screenshot = {
"id": 4,
"method": "Page.captureScreenshot",
"sessionId": session_id
}
await ws.send(json.dumps(screenshot))
response = await ws.recv()
data = json.loads(response)['result']['data']
# 保存截图
import base64
with open('screenshot.png', 'wb') as f:
f.write(base64.b64decode(data))
print("截图已保存为 screenshot.png")
# 运行
asyncio.run(control_chrome())
关键点:
- 启动Chrome时必须加
--remote-debugging-port=9222参数,--headless可选。 - CDP通信基于WebSocket,消息都是JSON格式,每个请求要有唯一ID。
- 要先创建目标(标签页),附加会话,然后在会话里发命令。
- 不同域的命令(如
Page.、Network.)需要对应权限,可能需要先调用Page.enable。
更简单的选择:
如果觉得底层协议太麻烦,可以用 pychrome 库(pip install pychrome)包装了一下:
import pychrome
# 连接已有浏览器
browser = pychrome.Browser(url="http://localhost:9222")
tab = browser.new_tab(url="https://www.example.com")
tab.start()
# 等加载
tab.wait(2)
# 调用CDP方法
result = tab.call_method("Page.captureScreenshot")
with open('screenshot_pychrome.png', 'wb') as f:
f.write(result['data'].decode('base64'))
一句话建议: 直接用 pychrome 库比裸写WebSocket方便多了。
赞~ 又见 fate 大神~
感觉有点意思,但是看了下代码,是不是支持的功能有点少?
selenium 在速度上还是慢了点
区别是更接近 Dev Protocol 吧,selenium 依赖 ChromeDriver,然而 ChromeDriver 还是使用 Dev Protocol 来操作 chrome (这段话单讲 chrome…)
功能多不多,主要看 dev protocol 开放的接口多不多,chrome 61 之后多了个 Network.requestIntercepted,看到这个 method,我就觉得 headless chrome 能够写爬虫了。
我觉得单论爬虫 splash 比 selenium 好用点
已 star,公司已经有在用不过是 node。这个 python 希望楼主继续加油!
Stared :D
挺好,近来研究自动化家庭框架。用得上。
看楼主破解了 ruby 的混乱工具,搭车问一下,python 有比较好的混乱工具么?
简单的方法就是转成 c 代码,需要保密的代码我直接用 go 写


