Skip to content

Browser Rendering

元气码农少女酱 edited this page Aug 20, 2026 · 6 revisions

浏览器渲染

当页面内容要 JS 跑完才有时,普通 HTTP 请求拿到的只是一个空壳。浏览器适配器会真的起一个 浏览器、加载页面、等渲染完成,然后把渲染后的 DOM 当作响应体返回。

resp = d.get("https://spa.example.com", adapter="browser")
print(resp.text)          # 渲染后的 HTML,不是初始 HTML

四个引擎怎么选

引擎 内核 反检测 浏览器本体 什么时候用
camoufox Firefox 最彻底(改的是内核层) 自带一份,约 1 GB Linux/macOS 默认;对方检测严
patchright Chromium 打过补丁的 Playwright patchright install chromium 要 Chromium 又要反检测
playwright 任意三选一 playwright install chromium 行为最可预期;自家页面、调试
DrissionPage Chromium 中等(CDP 直连) 用本机已装的 Chrome Windows 默认;不想再下浏览器

engine = "auto"(默认)按平台选:Windows → DrissionPage,其余 → camoufox

camoufox 最吃内存。 它是 Firefox 加一整套扩展,单个 context 的开销明显高于 Chromium 系。≤4 GB 内存的机器上把 max_pages 设成 1~2,否则会开始换页—— 请求从几秒变几分钟,看起来完全像卡死。

两步安装

pip install 只给 Python 包。浏览器本体要单独准备,详见安装

漏了第二步的话,请求会直接失败并告诉你该跑哪条命令:

FAILED_PRECONDITION: 引擎 camoufox 的浏览器本体未就绪,请执行 python -m camoufox fetch

不会自动下载——那会让第一个请求卡着下 1 GB 然后超时,而下载还在后台继续跑。

配置

[BROWSER]
enabled = true                 # 总开关。关掉后即使装了引擎也拒绝浏览器请求
engine = "auto"
browser = "chromium"           # 只对 playwright / patchright 有意义
headless = true
executable_path = ""           # 指向系统浏览器可省掉 150 MB 下载
args = []
no_sandbox = false             # 容器里通常要打开
user_agent = ""                # 留空则每次随机
viewport = { width = 1920, height = 1080 }
wait_until = "load"            # load / domcontentloaded / networkidle / commit
block_resources = ["image", "media", "font"]
max_pages = 4
allow_scripts = false

# 只对 camoufox 生效
locale = ""
humanize = false
geoip = false

[BROWSER.proxy]
gateway = ""
bypass_list = []

[BROWSER.timeout]
page_load = 30
script_exec = 60

wait_until —— 最影响耗时的一项

什么时候算加载完 备注
commit 收到响应头 最快,但 DOM 基本还是空的
domcontentloaded HTML 解析完 JS 还没跑完
load 所有资源加载完(默认) 大多数场景够用
networkidle 网络静默 500ms 最慢,页面有轮询/长连接时可能一直等到超时

带 WebSocket、SSE 或定时轮询的页面不要用 networkidle——网络永远不会静默, 每个请求都会耗满 page_load 才返回。

block_resources —— 最有效的提速手段

只要 HTML 的话,拦掉图片、字体、媒体能省掉大量时间和带宽。默认已经拦了这三类。 可选值:image media font stylesheet script xhr fetch websocket other

别拦 scriptxhr ——除非你确定不需要 JS 渲染的内容。拦了它们等于把 "用浏览器"这件事本身的意义拿掉了。

max_pages

同时打开的页面上限。无头浏览器每个页面几十到上百 MB,不设上限很容易把机器打满。 超出的请求排队等待。

在页面里执行 JS

resp = d.get(
    "https://example.com/product",
    adapter="browser",
    automation_script="return document.querySelector('#price').innerText",
)
print(resp.headers["x-ipclick-script-result"])

automation_script 是在页面里执行的 JavaScript,不是 Python。 返回值经 x-ipclick-script-result 响应头带回。

几点要知道的:

  • 默认关闭allow_scripts = false)。页面里的 JS 会自己发请求, [SECURITY] 那套 URL 策略(禁云元数据、禁内网)对它完全不起作用—— 放开它等于把 SSRF 防线让开一整条。只在确认调用方全部可信时打开。
  • 脚本写错(SyntaxError / ReferenceError)被判为参数错误, 直接 INVALID_ARGUMENT不重试——语法错重试三次还是语法错。
  • 脚本会自动规范化:可以写表达式、也可以写带 return 的函数体,两种都认。
  • 执行超时由 [BROWSER.timeout].script_exec 控制(默认 60s)。
  • 脚本文件较大时会被自动压缩传输,实测 8158 字节压到 350 字节,见 性能

其它渲染参数

d.get(url, adapter="browser",
      wait_for_selector="#content",   # 等某个元素出现
      wait_for_timeout=2000,          # 额外固定等待(毫秒)
      screenshot=True)                # 返回截图

wait_for_selector 比拉长 wait_for_timeout 好——前者一出现就继续,后者不管好坏都等满。

性能

浏览器路径做过一轮专门的优化——曾经实测有单次点击耗时 296 秒的情况。现在:

路径 耗时
热路径(浏览器已起来) 200~300 ms
冷启动(首次拉起浏览器) ~1.5 s
永久性导航错误(域名不存在等) 0.2 s(原先 16 s)

关键改动:

  1. 浏览器实例复用,并在每次使用前用 is_connected() 检查存活;死了就丢弃重建, 而不是拿着一个死连接反复超时。
  2. 超时预算随任务算:冷启动额外给 60s 宽限、常规开销给 15s, 不再用一个固定值同时套在冷热两条路径上。
  3. 永久性导航错误不重试ERR_NAME_NOT_RESOLVEDERR_CONNECTION_REFUSED 这类错误重试三次还是同样的结果。
  4. browser 先解析成具体引擎再做缓存键——否则 adapter="browser"adapter="camoufox" 会各自起一个浏览器,内存翻倍。
  5. 调用方已经放弃就不再执行:gRPC 的 deadline 到了之后继续渲染纯属浪费, 结果没人接收。

细节见性能

容器里跑

[BROWSER]
no_sandbox = true      # 同时会带上 --disable-dev-shm-usage
executable_path = "/usr/bin/chromium"
  • 容器默认 /dev/shm 只有 64 MB,Chromium 会崩——no_sandbox = true 会自动加 --disable-dev-shm-usage
  • 容器里通常没有 user namespace,需要 no_sandbox = true--cap-add=SYS_ADMIN
  • 关沙箱意味着页面里的代码更容易影响宿主进程,所以默认是关的,要由部署方明确选择。

camoufox 专属

[BROWSER]
locale = "zh-CN"     # 伪装的语言环境,留空则由 camoufox 生成
humanize = false     # 模拟人类鼠标移动;true 用默认时长,也可写秒数如 1.5
geoip = false        # 让时区/语言/经纬度与代理出口 IP 对上

humanize显著拖慢每次请求,默认关闭。

geoip 只有 [BROWSER.proxy].gateway 能生效——按请求指定的代理是在 context 上设的, 那时指纹早就生成完了。

排查

浏览器相关问题的定位路径见故障排查。快速自查:

ipclick config-info     # 看"浏览器引擎"与"本体是否就绪"两行

Web 管理端的总览页也会显示每个引擎的三态:未安装 / 包已装但本体未就绪 / 就绪

装引擎:也可以在 Web 端点按钮

/components 页列出四个渲染引擎的两级安装状态(Python 包 / 浏览器本体), 可以就地装包、下载本体、卸载。装完不用重启进程。

两级必须分开看:pip install "ipclick[camoufox]" 只装几 MB 的 Python 包,浏览器本体 (约 1 GB)是 python -m camoufox fetch 下的。只报一级的话,装了包没 fetch 的机器会 显示"已安装",而第一次请求会卡几分钟去下 1 GB 然后超时。

卸载只卸 Python 包——那 1 GB 本体还在磁盘上,界面会把路径和体积告诉你, 要回收空间自己删那个目录。

细节见 Web 管理端 · 组件

下一步

Clone this wiki locally