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?

13 回复

和 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())

关键点:

  1. 启动Chrome时必须加 --remote-debugging-port=9222 参数,--headless 可选。
  2. CDP通信基于WebSocket,消息都是JSON格式,每个请求要有唯一ID。
  3. 要先创建目标(标签页),附加会话,然后在会话里发命令。
  4. 不同域的命令(如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 写

好不容易找到的,已经 star,感谢楼主^_^

回到顶部