用 CDP 遥控本机 Chrome:批量截图、抓数据、绕过反爬

自动化 2026-09-23 17:01 · 34 次阅读 ·CDP,Chrome,爬虫,截图

CDP 的工作原理:脚本通过 WebSocket 驱动 Chrome

为什么要这条路

服务器上装 Selenium 要配 driver、要装 headless 浏览器,100 多 MB 起步。而机器上本来就有一个开着远程调试的 Chrome:

chrome --remote-debugging-port=9223 --no-sandbox

直接连上去就行。省事,而且它是真的浏览器,带完整 JS 引擎和 cookie。

最小可用代码

import json, urllib.request, websocket

# 新建标签页
req = urllib.request.Request("http://127.0.0.1:9223/json/new?about:blank", method="PUT")
tab = json.load(urllib.request.urlopen(req, timeout=10))

ws = websocket.create_connection(tab["webSocketDebuggerUrl"], timeout=60)
_i = 0
def send(method, **params):
    global _i
    _i += 1
    ws.send(json.dumps({"id": _i, "method": method, "params": params}))
    while True:
        r = json.loads(ws.recv())
        if r.get("id") == _i:
            return r

send("Page.enable")
send("Page.navigate", url="https://例子.com")

三件最常用的事

1. 读页面数据

def ev(expr):
    r = send("Runtime.evaluate", expression=expr, returnByValue=True)
    return r.get("result", {}).get("result", {}).get("value")

print(ev("document.title"))
print(ev("JSON.stringify([...document.querySelectorAll('a')].map(a=>a.href).slice(0,20))"))

2. 模拟手机截图

send("Emulation.setDeviceMetricsOverride", width=390, height=844,
     deviceScaleFactor=2, mobile=True)
send("Page.navigate", url=url)
time.sleep(7)                      # 等首屏渲染,别急着截
shot = send("Page.captureScreenshot", format="png", captureBeyondViewport=True)
open("shot.png", "wb").write(base64.b64decode(shot["result"]["data"]))

captureBeyondViewport=True 才能截到整页,不然只有一屏。

3. 关缓存重载

send("Network.enable")
send("Network.setCacheDisabled", cacheDisabled=True)

改完样式后验证,一定要关缓存,否则你看到的是旧 CSS,会得出错误结论。

反爬:别硬刚,换条路

真实案例:要扒一个博客联盟的成员名单。成员列表页面上,名字都是普通文字,但链接不是 <a> 标签 ——
是 JS 绑的点击事件,document.querySelectorAll('a') 只能拿到 2 个外链。浏览器里怎么点都拿不全。

换个思路:成员项其实链到站内详情页(href="/blog/600.html"),真实网址在详情页的
「查看TA的网站」上。于是关掉浏览器,纯 HTTP 请求 + 正则,31 个站几秒钟抓完:

m = re.search(r'href="(https?://[^"]+)"[^>]*>\s*(?:<[^>]+>\s*)*查看\s*TA\s*的网站', html)

结论:浏览器是用来「看清结构」的,看清了就该换成 HTTP 直连批量干。一个页面要开 7 秒,
31 个就是 3 分半;HTTP 版几秒钟。别在浏览器里做批量。

踩过的坑

  • pkill -f "关键词" 会杀掉自己:-f 匹配整条命令行,而你的命令行里就含这个关键词。
    用端口找 pid 更安全:ss -ltnp | grep ':5006' | grep -oP 'pid=\K[0-9]+'
  • 中文文件名在 CDP 里会带来 URL 编码麻烦,截图统一用域名做文件名
  • 截图完必须自检:用 ImageStat 算变化度,低于 20 的基本是错误页(Cloudflare 验证页、
    SSL 报错页、纯色跳转页都这样),别把错误页当成果交出去
  • 等页面渲染:7 秒是多数博客的安全值;有懒加载的站要再滚一下 (window.scrollTo(0,300) 再滚回来)

继续看

全部 →