flowchart TB
ide["Cursor IDE / 终端"]
legacy["chrome-debug-legacy<br/>standalone-chrome-debug"]
modern["chrome / chrome-debug<br/>standalone-chrome Selenium 4"]
rs["RSelenium 1.7.9"]
se["CRAN selenium"]
ide -->|"profile debug-legacy"| legacy
ide -->|"up chrome 或 profile debug"| modern
legacy -->|"localhost:5555 /wd/hub"| rs
modern -->|"localhost:5555"| seCursor IDE 下 Docker Selenium 可复用工作流
多仓库共用 Compose / Tasks:RSelenium 1.7.9 现行与 CRAN selenium 迁移
摘要
本文整理在 Cursor IDE 中,用 Docker Desktop + Compose +(可选)Docker 扩展 / Tasks,为各业务仓库提供可复制的 Selenium Chrome 浏览器自动化环境。经验来源于教学成绩仓库 Rexam 的实验提交抓取流程,抽象后供 harness 及任意业务仓库复用。
客户端分两条线,不要混用镜像与 R 包:
| 客户端 | Grid | Compose 服务 | 说明 |
|---|---|---|---|
| RSelenium 1.7.9(现行) | Selenium 3 JSON Wire | chrome-debug-legacy(--profile debug-legacy) |
依赖已废弃的 standalone-chrome-debug;对 Selenium 4 的 standalone-chrome 上 remDr$open() 常挂起 |
CRAN selenium(迁移方向) |
Selenium 4 W3C | chrome 或 chrome-debug(--profile debug) |
无头省内存;调试用同一镜像 + noVNC :17900 |
核心结论:
- 每个仓库可各自放置一份
docker-compose.selenium.yml;同一标签的镜像全机共用。现行线与迁移线是两套镜像(*-debug与standalone-chrome),磁盘上会各占一份。 - 同时只跑一个 映射主机
5555的服务;用完即down。 - 调试时 勿映射主机 5901(Windows 常保留 5901–6000);新旧 debug 的传统 VNC 均用 15900:5900。仅 Selenium 4 debug 提供浏览器 noVNC :17900。
- 可复制最小集 = 1 个 Compose 文件 + 对应客户端的
up/ 就绪检查 /down;Cursor Task 为可选加速器。Windows 就绪检查用curl.exe。Selenium 4 查/status,RSelenium / Selenium 3 查/wd/hub/status。
1. 适用场景与非目标
1.1 适用
- 学期末 / 偶发批次:登录校内或外部站点,抓取动态页面(iframe、点击、分页等)。
- 希望减少手工:不再每次手敲
docker run、不再默认依赖 tvnViewer。 - 多仓库(A / B / …)希望 同一套启动习惯,仅改项目名与端口策略。
1.2 非目标
- 不替代合法登录与权限;账号密码仍用本机密钥环(如 R
keyring),勿写入仓库。 - 不保证某一具体站点选择器长期有效(DOM 改版需改业务脚本)。
- 不以 Cursor 内置浏览器 / Browser MCP 作为批次爬虫主路径。
1.3 参考实现(来源)
| 工件 | 路径(Rexam 示例) |
|---|---|
| Compose | record-workflow/docker-compose.selenium.yml |
| Cursor Tasks | .vscode/tasks.json |
| 流程说明 | record-workflow/task-scrape-lab-submit.qmd |
| 业务脚本 | record-stat/code/03-lab-submit-01-scrape.R |
本文给出的模板已 去业务化(项目名、路径改为占位符),可直接拷入其他仓库。
2. 架构总览
2.1 演进对照
| 旧习惯 | 推荐习惯 | |
|---|---|---|
| 启动 | 手敲 docker run,侧栏残留旧容器 |
Compose + 固定服务名 |
| IDE | 仅终端 | Cursor Docker 扩展查看状态;Tasks 一键启停 |
| 可视化 | 默认 VNC 常映射 5901 | 新旧 debug 均用 15900;仅 Selenium 4 debug 另开 noVNC :17900 |
| 客户端 | 仅 RSelenium 1.7.9 + *-debug 镜像 |
现行仍走 debug-legacy;新项目用 CRAN selenium + standalone-chrome |
| 多仓库 | 命令不一致、易撞端口 | 统一模板;name / container_name 按项目区分 |
2.2 为何不要映射主机 5901
Windows(尤其 Hyper-V)常通过 excluded port range 保留 5901–6000。此时:
bind: An attempt was made to access a socket in a way forbidden by its access permissions
在 Cursor Docker 扩展里对旧容器点 Start 也会失败。处理:日常不映射 VNC;若需要,传统 VNC 用 15900:5900,浏览器 noVNC 用 17900:7900(或其它非保留端口),禁止 5901。
自查保留区间(PowerShell / CMD):
netsh interface ipv4 show excludedportrange protocol=tcp3. 磁盘与内存:多仓库会不会「堆满」容器?
3.1 结论(先看这个)
| 对象 | 是否因「每仓库一份 yml」而暴涨 | 说明 |
|---|---|---|
| Compose / Tasks 文本 | 否 | 每份数 KB |
镜像 standalone-chrome |
否(通常一份) | Selenium 4 线;多项目共用同一 image |
镜像 standalone-chrome-debug |
否(通常一份) | RSelenium 1.7.9 线;已废弃但仍被 JSON Wire 客户端需要 |
| 容器 | 仅在你 up 之后存在 |
down 后可删除;残留可写层通常远小于镜像 |
| 正在运行的 Chrome | — | 主要吃 RAM/CPU;内存紧时优先管这个 |
因此:可以为每个仓库都放 docker/docker-compose.selenium.yml,并设不同 name: project-B-selenium。 磁盘压力来自「镜像版本堆积」和「从不清理的已停止容器」,不是 yml 份数。
3.2 推荐纪律(内存紧时)
- 同时只跑一个 Selenium(默认都用主机
5555时也只能跑一个)。 - 用完:
docker compose ... down --remove-orphans(或 TaskSelenium: stop (remove containers))。确认真空闲再--rmi all。 - 偶尔清理:
docker container prune;确认无用后再docker image prune。 - 必须两仓库并行时:第二套改
"5556:4444",客户端port = 5556L。
4. 可复制最小集
每个业务仓库建议落地:
<repo>/
docker/
docker-compose.selenium.yml # 或放在 tools/、.devcontainer/ 旁,路径自定
.vscode/
tasks.json # 可选
把下文中的 projectb 换成短名(如 rexam、harness-demo),保证:
- Compose 顶层
name:全局不撞车(影响默认网络名等); container_name:全局唯一(否则docker会拒绝或覆盖混乱)。
5. Compose 模板(拷贝即用)
权威副本在 scripts/docker-selenium/docker-compose.selenium.yml(资产索引:scripts/docker-selenium/index.qmd)。下文与之保持一致。将文件拷到业务仓库的 docker/docker-compose.selenium.yml 后,修改 name 与 container_name。也可用:
.\scripts\powershell\Install-Harness.ps1 -InstallProfile docker-selenium -ProjectRoot "D:\path\to\your-repo"# 见 scripts/docker-selenium/docker-compose.selenium.yml 文件头注释
name: projectb-selenium
services:
chrome:
image: selenium/standalone-chrome:latest
container_name: projectb-chrome
shm_size: 2gb
ports:
- "5555:4444"
environment:
- SE_NODE_MAX_SESSIONS=1
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
- SE_START_VNC=false
restart: "no"
chrome-debug:
profiles: ["debug"]
image: selenium/standalone-chrome:latest
container_name: projectb-chrome-debug
shm_size: 2gb
ports:
- "5555:4444"
- "15900:5900"
- "17900:7900"
environment:
- SE_NODE_MAX_SESSIONS=1
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
restart: "no"
chrome-debug-legacy:
profiles: ["debug-legacy"]
image: selenium/standalone-chrome-debug:latest
container_name: projectb-chrome-debug-legacy
shm_size: 2gb
ports:
- "5555:4444"
- "15900:5900"
restart: "no"说明:
shm_size: 2gb:减轻 Chrome 在容器内因/dev/shm过小崩溃的概率。chrome、chrome-debug、chrome-debug-legacy不要同时 up(都抢主机5555)。debug-legacy仅供 RSelenium 1.7.9。镜像已废弃,新仓库不要把它当默认;需要可复现时可把标签钉成3.141.59。- Selenium 4 的 VNC/noVNC 已并入
standalone-chrome;debugprofile 面向 CRANselenium。 - 无头
chrome设SE_START_VNC=false以省内存;教学仓库若要可复现,可将 Selenium 4 线的:latest换成官方发布标签(如4.45.0-20260606)。
6. 标准操作指令
前置: Docker Desktop 状态为 Running。
6.1 启动
RSelenium 1.7.9(现行):
docker compose -f docker/docker-compose.selenium.yml --profile debug-legacy up -d chrome-debug-legacyCRAN selenium / Selenium 4 无头(迁移):
docker compose -f docker/docker-compose.selenium.yml up -d chrome首次会拉镜像,可能较慢;之后复用本地镜像。RSelenium 请不要对 up -d chrome(Selenium 4)抱期望:remDr$open() 常会挂起。
6.2 就绪检查
启动后等待约 10–20 秒。
Selenium 4:
curl.exe http://127.0.0.1:5555/statusRSelenium / Selenium 3:
curl.exe http://127.0.0.1:5555/wd/hub/statusWindows PowerShell 中 curl 常是 Invoke-WebRequest 的别名,输出不是 curl 的 JSON;请显式调用 curl.exe。
响应 JSON 中应含类似 "message": "Selenium Grid ready." 或旧版 status 字段。
亦可用浏览器打开对应 URL。
6.3 停止
日常(拆掉容器与默认网络,保留镜像,下次 up 不必重拉):
docker compose -f docker/docker-compose.selenium.yml --profile debug --profile debug-legacy down --remove-orphans须带上 两个 profile,否则曾启动的 chrome-debug 或 chrome-debug-legacy 可能残留。--remove-orphans 顺带清掉本项目里已不再定义的旧容器。
若学期结束、确定本机其它仓库也不再用 standalone-chrome / standalone-chrome-debug,可连镜像删除以腾磁盘(下次 up 会重新拉取约 1–2GB+):
docker compose -f docker/docker-compose.selenium.yml --profile debug --profile debug-legacy down --remove-orphans --rmi all6.4(可选)Selenium 4 调试 + noVNC / VNC
docker compose -f docker/docker-compose.selenium.yml --profile debug up -d chrome-debug优先用浏览器打开 http://127.0.0.1:17900/(noVNC)。也可让 VNC 客户端连接 localhost:15900。默认密码多为 secret。供 CRAN selenium 观察页面;日常批次可完全跳过。
6.5(可选)RSelenium 1.7.9 调试 + VNC
即 §6.1 的 debug-legacy。旧镜像没有 noVNC(无 7900)。VNC 客户端连接 localhost:15900(勿用 5901)。密码多为 secret。
6.6 状态与日志
docker ps --filter name=projectb-chrome
docker logs --tail 50 projectb-chrome-debug-legacy将过滤器换成你的 container_name(projectb-chrome / projectb-chrome-debug / projectb-chrome-debug-legacy)。
7. Cursor IDE 集成
7.1 Docker 扩展
- 侧栏 Containers 可查看/停止正在运行的容器。
- 不要依赖「多年前
docker run留下的旧容器」点 Start(易踩 5901 或过时端口)。 - 以 当前仓库 Compose 起的容器(如
projectb-chrome)为准。
7.2 Tasks 模板(可选)
保存为 .vscode/tasks.json(若已有 tasks,合并进 tasks 数组即可)。权威副本:scripts/docker-selenium/vscode-tasks-selenium.json。Install-Harness -InstallProfile docker-selenium 会写成 .vscode/tasks-selenium.json(不覆盖已有 tasks.json)。
{
"version": "2.0.0",
"tasks": [
{
"label": "Selenium: start (headless, Selenium 4 / CRAN selenium)",
"type": "shell",
"command": "docker compose -f docker/docker-compose.selenium.yml up -d chrome",
"options": { "cwd": "${workspaceFolder}" },
"problemMatcher": [],
"presentation": { "reveal": "always", "panel": "shared" }
},
{
"label": "Selenium: start (debug Selenium 4 + VNC :15900 / noVNC :17900)",
"type": "shell",
"command": "docker compose -f docker/docker-compose.selenium.yml --profile debug up -d chrome-debug",
"options": { "cwd": "${workspaceFolder}" },
"problemMatcher": [],
"presentation": { "reveal": "always", "panel": "shared" }
},
{
"label": "Selenium: start (legacy debug for RSelenium 1.7.9)",
"type": "shell",
"command": "docker compose -f docker/docker-compose.selenium.yml --profile debug-legacy up -d chrome-debug-legacy",
"options": { "cwd": "${workspaceFolder}" },
"problemMatcher": [],
"presentation": { "reveal": "always", "panel": "shared" }
},
{
"label": "Selenium: stop (remove containers)",
"type": "shell",
"command": "docker compose -f docker/docker-compose.selenium.yml --profile debug --profile debug-legacy down --remove-orphans",
"options": { "cwd": "${workspaceFolder}" },
"problemMatcher": [],
"presentation": { "reveal": "always", "panel": "shared" }
},
{
"label": "Selenium: stop and remove images",
"type": "shell",
"command": "docker compose -f docker/docker-compose.selenium.yml --profile debug --profile debug-legacy down --remove-orphans --rmi all",
"options": { "cwd": "${workspaceFolder}" },
"problemMatcher": [],
"presentation": { "reveal": "always", "panel": "shared" }
},
{
"label": "Selenium: status",
"type": "shell",
"command": "docker compose -f docker/docker-compose.selenium.yml --profile debug --profile debug-legacy ps; curl.exe http://127.0.0.1:5555/status; curl.exe http://127.0.0.1:5555/wd/hub/status",
"options": { "cwd": "${workspaceFolder}" },
"problemMatcher": [],
"presentation": { "reveal": "always", "panel": "shared" }
}
]
}使用:Ctrl+Shift+P → Tasks: Run Task → 选择对应项。
路径若不是 docker/docker-compose.selenium.yml,改 Task 与文档中的 -f 即可。
8. 客户端连接
端口均为主机 5555。先按 §6 启动匹配的 Grid,再开客户端。
8.1 现行:RSelenium 1.7.9
对应 --profile debug-legacy。默认会话路径为 /wd/hub。
library(RSelenium)
remDr <- remoteDriver(
remoteServerAddr = "localhost",
port = 5555L,
browserName = "chrome"
)
remDr$open()
remDr$maxWindowSize()
# ... 业务操作 ...
remDr$close()
rm(remDr)
gc()若 open() 挂起且 Grid 是 standalone-chrome(无 -debug),改用 chrome-debug-legacy,不要改 R 代码去「适配」Selenium 4。
8.2 迁移方向:CRAN selenium
对应 up -d chrome 或 --profile debug。包文档:https://cran.r-project.org/package=selenium。
library(selenium)
session <- SeleniumSession$new(
browser = "chrome",
host = "localhost",
port = 5555L
)
# ... 业务操作,例如 session$navigate("https://example.com") ...
session$close()凭证建议:
# 一次性设置(示例)
# keyring::keyring_create("lab")
# keyring::key_set("usr", keyring = "lab")
# keyring::key_set("password", keyring = "lab")
# keyring::key_get("usr", keyring = "lab")勿将密码写入 git。其他语言(Python selenium、Playwright 连已有 Grid 等)在 Selenium 4 线上同样指向 http://localhost:5555。
9. 多仓库落地检查清单
复制到新仓库 Project B 时按序勾选:
- [ ](可选)拷贝/合并
.vscode/tasks.json。
10. 故障排查
| 现象 | 可能原因 | 处理 |
|---|---|---|
扩展 Start 旧容器失败,含 access permissions |
主机端口落在 Windows 保留段(如 5901) | 弃用旧容器;用本文 Compose;VNC 改 15900,noVNC 用 17900 |
curl 返回 HTML / 方法对象而非 JSON |
PowerShell 把 curl 当成 Invoke-WebRequest |
改用 curl.exe |
remDr$open() 失败 / 挂起 / $id 为 NA |
把 Selenium 4 standalone-chrome 配给了 RSelenium 1.7.9 |
改用 --profile debug-legacy;就绪查 /wd/hub/status |
remDr$open() 连接重置 |
容器未就绪或未启动 | 等 15s;查对应 status URL;看 docker logs |
CRAN selenium 连不上 |
仍跑着 legacy debug 容器 | down 后 up -d chrome 或 --profile debug |
port is already allocated |
另一套 Selenium 仍占用 5555 | docker ps 后 down,或换 5556 |
| Chrome 容器内崩溃 | /dev/shm 过小 |
保持 shm_size: 2gb |
| 镜像拉取很慢/失败 | 网络 | 配置镜像加速或稍后重试;与代理文档(harness 内 v2ray 指南)配合 |
| 登录/选择器失败 | 站点改版或验证码 | 属业务层;RSelenium 用 VNC :15900;新线用 noVNC :17900 |
11. 在 harness 中的位置
本文档路径:
harness/docs/cursor-docker-selenium-workflow.qmd
可单独拷贝的资产(canonical):
harness/scripts/docker-selenium/docker-compose.selenium.yml
harness/scripts/docker-selenium/vscode-tasks-selenium.json
harness/scripts/docker-selenium/index.qmd
业务仓库(如 Rexam)建议保留 指向本文的链接 + 本仓库实际使用的 Compose(可含项目专用 name),避免两处长文双轨失同步。
版本约定: 本文 YAML 中 version / date 随修订递增;重大变更(默认端口、镜像标签策略)在摘要下追加简短 changelog。
Changelog
| 版本 | 日期 | 说明 |
|---|---|---|
| 1.3.1 | 2026-08-24 | 补全 down --remove-orphans;可选 --rmi all 删除本 compose 用过的镜像 |
| 1.3.0 | 2026-08-24 | 增加 debug-legacy(standalone-chrome-debug)供 RSelenium 1.7.9;debug 保留给 Selenium 4 / CRAN selenium |
| 1.2.0 | 2026-08-24 | 资产从 templates/docker-selenium/ 迁到 scripts/docker-selenium/;增加 Install-Harness profile docker-selenium |
| 1.1.0 | 2026-08-24 | 去掉已废弃的 standalone-chrome-debug;debug 改用同一镜像 + noVNC :17900;Windows 就绪检查改 curl.exe;架构图改为 Quarto {mermaid} |
| 1.0.0 | 2026-08-24 | 初版:从 Rexam 实验抓取工作流抽象为多仓库可复制指南 |
12. 一页速查(可打印)
# 0. Docker Desktop = Running
# A. 现行 RSelenium 1.7.9
docker compose -f docker/docker-compose.selenium.yml --profile debug-legacy up -d chrome-debug-legacy
curl.exe http://127.0.0.1:5555/wd/hub/status
# R: remoteDriver(..., port = 5555L); remDr$open()
# B. 迁移:CRAN selenium + Selenium 4
docker compose -f docker/docker-compose.selenium.yml up -d chrome
curl.exe http://127.0.0.1:5555/status
# R: selenium::SeleniumSession$new(browser="chrome", host="localhost", port=5555L)
# 调试(Selenium 4): --profile debug up -d chrome-debug
# 浏览器: http://127.0.0.1:17900/ VNC: localhost:15900
# 停止(两个 profile + 孤儿容器):
docker compose -f docker/docker-compose.selenium.yml --profile debug --profile debug-legacy down --remove-orphans
# 连镜像删除(腾磁盘;其它项目若还用这两份 image 则不要执行):
# docker compose -f docker/docker-compose.selenium.yml --profile debug --profile debug-legacy down --remove-orphans --rmi all
# 规则:勿用主机 5901;5555 上同时只跑一个服务;yml 可多仓复制。