Files
web-access/index.html
kang 2686d94ab6 init: Web-Access Skill 源码解析研究页
- 克隆 eze-is/web-access 完整源码
- 创建功能说明网页(架构、API、对比、评估)
- 端口 4310

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 14:36:22 +08:00

853 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web-Access Skill - 源码解析与功能说明</title>
<style>
:root {
--bg: #0a0a0f;
--surface: #12121a;
--surface2: #1a1a26;
--border: #2a2a3a;
--text: #e0e0e8;
--text2: #888899;
--accent: #6c5ce7;
--accent2: #a855f7;
--green: #10b981;
--orange: #f59e0b;
--red: #ef4444;
--blue: #3b82f6;
--cyan: #06b6d4;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.7;
overflow-x: hidden;
}
/* Hero */
.hero {
position: relative;
min-height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 80px 24px 60px;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(ellipse at 50% 50%, rgba(108,92,231,0.08) 0%, transparent 60%),
radial-gradient(ellipse at 20% 80%, rgba(168,85,247,0.06) 0%, transparent 50%);
animation: drift 20s ease-in-out infinite alternate;
}
@keyframes drift {
0% { transform: translate(0, 0) rotate(0deg); }
100% { transform: translate(-30px, 20px) rotate(2deg); }
}
.hero-content { position: relative; z-index: 1; }
.hero h1 {
font-size: clamp(2rem, 5vw, 3.5rem);
font-weight: 800;
letter-spacing: -0.03em;
background: linear-gradient(135deg, #e0e0e8, #a855f7, #6c5ce7);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 16px;
}
.hero .subtitle {
font-size: 1.15rem;
color: var(--text2);
max-width: 600px;
margin: 0 auto 32px;
}
.badge-row {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
}
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
border-radius: 20px;
font-size: 0.82rem;
font-weight: 600;
border: 1px solid var(--border);
background: var(--surface);
}
.badge .dot {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
}
.badge .dot.green { background: var(--green); }
.badge .dot.orange { background: var(--orange); }
.badge .dot.blue { background: var(--blue); }
.badge .dot.purple { background: var(--accent2); }
/* Container */
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 24px;
}
/* Section */
section {
margin-bottom: 64px;
}
.section-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 24px;
display: flex;
align-items: center;
gap: 10px;
}
.section-title .icon {
width: 32px;
height: 32px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1rem;
flex-shrink: 0;
}
/* Cards */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 16px;
}
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 24px;
transition: border-color 0.2s, transform 0.2s;
}
.card:hover {
border-color: var(--accent);
transform: translateY(-2px);
}
.card h3 {
font-size: 1.05rem;
font-weight: 700;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.card p, .card li {
font-size: 0.92rem;
color: var(--text2);
line-height: 1.7;
}
.card ul {
list-style: none;
padding-left: 0;
}
.card ul li::before {
content: '>';
color: var(--accent);
margin-right: 8px;
font-weight: bold;
font-family: monospace;
}
/* Architecture diagram */
.arch-box {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 32px;
overflow-x: auto;
}
.arch-flow {
display: flex;
align-items: center;
justify-content: center;
gap: 0;
flex-wrap: wrap;
padding: 16px 0;
}
.arch-node {
background: var(--surface2);
border: 1px solid var(--border);
border-radius: 10px;
padding: 16px 20px;
text-align: center;
min-width: 140px;
transition: border-color 0.2s;
}
.arch-node:hover { border-color: var(--accent2); }
.arch-node .label {
font-size: 0.78rem;
color: var(--text2);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 6px;
}
.arch-node .name {
font-size: 1rem;
font-weight: 700;
}
.arch-arrow {
color: var(--accent);
font-size: 1.3rem;
padding: 0 12px;
flex-shrink: 0;
}
/* API Table */
.api-table-wrap {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
}
.api-table {
width: 100%;
border-collapse: collapse;
font-size: 0.9rem;
}
.api-table th {
background: var(--surface2);
padding: 12px 16px;
text-align: left;
font-weight: 700;
font-size: 0.82rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text2);
border-bottom: 1px solid var(--border);
}
.api-table td {
padding: 10px 16px;
border-bottom: 1px solid var(--border);
vertical-align: top;
}
.api-table tr:last-child td { border-bottom: none; }
.api-table tr:hover td { background: rgba(108,92,231,0.04); }
.method-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 700;
font-family: monospace;
}
.method-badge.get { background: rgba(16,185,129,0.15); color: var(--green); }
.method-badge.post { background: rgba(59,130,246,0.15); color: var(--blue); }
code, .mono {
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 0.85em;
background: var(--surface2);
padding: 2px 6px;
border-radius: 4px;
color: var(--cyan);
}
/* File tree */
.file-tree {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 24px;
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 0.88rem;
line-height: 2;
}
.file-tree .dir { color: var(--accent2); }
.file-tree .file { color: var(--text2); }
.file-tree .comment { color: #555566; font-style: italic; }
/* Comparison */
.compare-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
@media (max-width: 700px) {
.compare-grid { grid-template-columns: 1fr; }
}
.compare-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 24px;
}
.compare-card h3 {
font-size: 1rem;
font-weight: 700;
margin-bottom: 12px;
}
.compare-card.highlight {
border-color: var(--accent);
background: linear-gradient(135deg, var(--surface), rgba(108,92,231,0.05));
}
.tag {
display: inline-block;
padding: 3px 10px;
border-radius: 6px;
font-size: 0.78rem;
font-weight: 600;
margin-bottom: 8px;
}
.tag.green { background: rgba(16,185,129,0.15); color: var(--green); }
.tag.red { background: rgba(239,68,68,0.15); color: var(--red); }
.tag.purple { background: rgba(168,85,247,0.15); color: var(--accent2); }
.stat-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
margin-bottom: 24px;
}
.stat-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 10px;
padding: 18px;
text-align: center;
}
.stat-card .num {
font-size: 1.8rem;
font-weight: 800;
background: linear-gradient(135deg, var(--accent), var(--accent2));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.stat-card .label {
font-size: 0.82rem;
color: var(--text2);
margin-top: 4px;
}
/* Philosophy */
.philosophy-steps {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
}
.step-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 24px;
position: relative;
}
.step-num {
position: absolute;
top: -12px;
left: 20px;
background: var(--accent);
color: white;
width: 28px;
height: 28px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.82rem;
font-weight: 800;
}
.step-card h4 {
margin-top: 8px;
margin-bottom: 8px;
font-size: 0.95rem;
}
.step-card p {
font-size: 0.85rem;
color: var(--text2);
}
/* Code block */
.code-block {
background: #0d0d15;
border: 1px solid var(--border);
border-radius: 10px;
padding: 20px;
overflow-x: auto;
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 0.85rem;
line-height: 1.8;
color: var(--text2);
margin: 16px 0;
}
.code-block .kw { color: var(--accent2); }
.code-block .str { color: var(--green); }
.code-block .cmt { color: #555566; }
.code-block .fn { color: var(--cyan); }
/* Footer */
footer {
border-top: 1px solid var(--border);
padding: 32px 24px;
text-align: center;
color: var(--text2);
font-size: 0.85rem;
}
footer a {
color: var(--accent2);
text-decoration: none;
}
a { color: var(--accent2); text-decoration: none; }
a:hover { text-decoration: underline; }
/* Verdict */
.verdict-box {
background: linear-gradient(135deg, var(--surface), rgba(108,92,231,0.06));
border: 1px solid var(--accent);
border-radius: 12px;
padding: 28px;
}
.verdict-box h3 {
font-size: 1.15rem;
font-weight: 700;
margin-bottom: 12px;
}
.verdict-box p, .verdict-box li {
font-size: 0.92rem;
color: var(--text2);
line-height: 1.8;
}
.verdict-box ul {
padding-left: 20px;
margin: 8px 0;
}
</style>
</head>
<body>
<!-- Hero -->
<header class="hero">
<div class="hero-content">
<h1>Web-Access Skill</h1>
<p class="subtitle">
Claude Code 联网增强 Skill &mdash; 三层通道调度 + CDP 浏览器自动化 + 站点经验积累
</p>
<div class="badge-row">
<span class="badge"><span class="dot green"></span> v2.4.1</span>
<span class="badge"><span class="dot orange"></span> 1,800+ Stars</span>
<span class="badge"><span class="dot blue"></span> MIT License</span>
<span class="badge"><span class="dot purple"></span> by 一泽 Eze</span>
</div>
</div>
</header>
<div class="container">
<!-- Stats -->
<div class="stat-row">
<div class="stat-card">
<div class="num">5</div>
<div class="label">联网通道</div>
</div>
<div class="stat-card">
<div class="num">14</div>
<div class="label">CDP API 端点</div>
</div>
<div class="stat-card">
<div class="num">573</div>
<div class="label">行核心代码</div>
</div>
<div class="stat-card">
<div class="num">29</div>
<div class="label">Commits</div>
</div>
<div class="stat-card">
<div class="num">0</div>
<div class="label">外部依赖</div>
</div>
</div>
<!-- Architecture -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(108,92,231,0.15)">&#9881;</span>
架构总览
</h2>
<div class="arch-box">
<div class="arch-flow">
<div class="arch-node">
<div class="label">用户指令</div>
<div class="name">Claude Code</div>
</div>
<div class="arch-arrow">&rarr;</div>
<div class="arch-node" style="border-color:var(--accent)">
<div class="label">决策层</div>
<div class="name">SKILL.md</div>
</div>
<div class="arch-arrow">&rarr;</div>
<div class="arch-node">
<div class="label">通道选择</div>
<div class="name" style="font-size:0.85rem">WebSearch / WebFetch<br>curl / Jina / CDP</div>
</div>
<div class="arch-arrow">&rarr;</div>
<div class="arch-node">
<div class="label">浏览器层</div>
<div class="name">cdp-proxy.mjs</div>
</div>
<div class="arch-arrow">&rarr;</div>
<div class="arch-node" style="border-color:var(--green)">
<div class="label">目标</div>
<div class="name">用户 Chrome</div>
</div>
</div>
<p style="text-align:center;color:var(--text2);font-size:0.85rem;margin-top:16px;">
SKILL.md 提供策略哲学 &rarr; AI 自主推理选通道 &rarr; CDP Proxy 通过 WebSocket 直连 Chrome
</p>
</div>
</section>
<!-- Core Capabilities -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(16,185,129,0.15)">&#9733;</span>
核心能力
</h2>
<div class="card-grid">
<div class="card">
<h3>&#128268; 智能通道调度</h3>
<p>根据任务场景自动选择最优联网方式:</p>
<ul>
<li><strong>WebSearch</strong> &mdash; 搜索摘要、关键词结果</li>
<li><strong>WebFetch</strong> &mdash; 已知 URL 定向提取信息</li>
<li><strong>curl</strong> &mdash; 需要原始 HTML/JSON-LD</li>
<li><strong>Jina</strong> &mdash; 网页转 Markdown省 token</li>
<li><strong>CDP 浏览器</strong> &mdash; 动态页面、登录态</li>
</ul>
</div>
<div class="card">
<h3>&#127760; CDP 浏览器操作</h3>
<p>直连用户日常 Chrome天然携带所有登录态。通过 HTTP API 提供:</p>
<ul>
<li>新建/关闭 Tab导航、后退</li>
<li>执行任意 JavaScript</li>
<li>JS 点击 + CDP 真实鼠标事件</li>
<li>文件上传(绕过文件对话框)</li>
<li>截图(含视频当前帧)</li>
<li>滚动触发懒加载</li>
</ul>
</div>
<div class="card">
<h3>&#9889; 并行分治</h3>
<p>多目标任务自动分发子 Agent 并行执行:</p>
<ul>
<li>共享一个 Chrome + Proxy</li>
<li>Tab 级隔离,无竞态风险</li>
<li>抓取内容不进主 Agent 上下文</li>
<li>总耗时 &asymp; 单任务时长</li>
</ul>
</div>
<div class="card">
<h3>&#128218; 站点经验积累</h3>
<p>按域名存储操作经验,跨 session 复用:</p>
<ul>
<li>URL 模式、平台特征、已知陷阱</li>
<li>小红书 xsec_token 机制</li>
<li>自动匹配目标站点经验</li>
<li>操作成功后自动更新经验</li>
</ul>
</div>
<div class="card">
<h3>&#127909; 媒体提取</h3>
<p>从 DOM 直取图片/视频 URL或对视频进行定点截帧分析</p>
<ul>
<li>eval 操控 &lt;video&gt; 元素</li>
<li>seek 到任意时间点 + screenshot</li>
<li>图片 URL 直接提取,无需全页截图</li>
</ul>
</div>
<div class="card">
<h3>&#128270; 信息核实</h3>
<p>追溯一手来源而非二手报道:</p>
<ul>
<li>政策法规 &rarr; 发布机构官网</li>
<li>企业公告 &rarr; 公司官方页面</li>
<li>学术声明 &rarr; 原始论文</li>
<li>避免循环引证假象</li>
</ul>
</div>
</div>
</section>
<!-- File Structure -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(59,130,246,0.15)">&#128193;</span>
源码结构
</h2>
<div class="file-tree">
<span class="dir">web-access/</span><br>
&nbsp;&nbsp;<span class="file">SKILL.md</span> <span class="comment">&larr; 核心:联网策略 + 浏览哲学 + API 指引371 行AI 的"大脑"</span><br>
&nbsp;&nbsp;<span class="file">README.md</span> <span class="comment">&larr; 项目说明 + 安装指南</span><br>
&nbsp;&nbsp;<span class="dir">scripts/</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="file">cdp-proxy.mjs</span> <span class="comment">&larr; CDP Proxy 服务器573 行 JS零外部依赖</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="file">check-deps.sh</span> <span class="comment">&larr; 环境检查 + 自动启动 Proxy</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="file">match-site.sh</span> <span class="comment">&larr; 站点经验匹配脚本</span><br>
&nbsp;&nbsp;<span class="dir">references/</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="file">cdp-api.md</span> <span class="comment">&larr; CDP API 详细参考文档</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="dir">site-patterns/</span> <span class="comment">&larr; 站点经验文件(按域名存储)</span><br>
</div>
</section>
<!-- CDP Proxy API -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(6,182,212,0.15)">&#128640;</span>
CDP Proxy API &mdash; 14 个端点
</h2>
<p style="color:var(--text2);margin-bottom:16px;font-size:0.92rem">
Proxy 监听 <code>localhost:3456</code>,通过 WebSocket 直连 Chrome DevTools Protocol所有操作通过 curl 调用。
</p>
<div class="api-table-wrap">
<table class="api-table">
<thead>
<tr><th>端点</th><th>方法</th><th>功能</th></tr>
</thead>
<tbody>
<tr><td><code>/health</code></td><td><span class="method-badge get">GET</span></td><td>健康检查,返回连接状态</td></tr>
<tr><td><code>/targets</code></td><td><span class="method-badge get">GET</span></td><td>列出所有已打开的页面 Tab</td></tr>
<tr><td><code>/new?url=</code></td><td><span class="method-badge get">GET</span></td><td>创建新后台 Tab自动等待加载完成</td></tr>
<tr><td><code>/close?target=</code></td><td><span class="method-badge get">GET</span></td><td>关闭指定 Tab</td></tr>
<tr><td><code>/navigate?target=&url=</code></td><td><span class="method-badge get">GET</span></td><td>在已有 Tab 中导航(自动等待加载)</td></tr>
<tr><td><code>/back?target=</code></td><td><span class="method-badge get">GET</span></td><td>后退一页</td></tr>
<tr><td><code>/info?target=</code></td><td><span class="method-badge get">GET</span></td><td>获取页面 title / URL / readyState</td></tr>
<tr><td><code>/eval?target=</code></td><td><span class="method-badge post">POST</span></td><td>执行任意 JS 表达式,支持 async</td></tr>
<tr><td><code>/click?target=</code></td><td><span class="method-badge post">POST</span></td><td>JS 层面点击el.click()</td></tr>
<tr><td><code>/clickAt?target=</code></td><td><span class="method-badge post">POST</span></td><td>CDP 真实鼠标事件(绕过反自动化)</td></tr>
<tr><td><code>/setFiles?target=</code></td><td><span class="method-badge post">POST</span></td><td>文件上传(绕过文件对话框)</td></tr>
<tr><td><code>/scroll?target=&y=</code></td><td><span class="method-badge get">GET</span></td><td>滚动页面(触发懒加载,等待 800ms</td></tr>
<tr><td><code>/screenshot?target=&file=</code></td><td><span class="method-badge get">GET</span></td><td>截图保存到文件或返回二进制</td></tr>
</tbody>
</table>
</div>
</section>
<!-- Design Philosophy -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(245,158,11,0.15)">&#128161;</span>
设计哲学
</h2>
<p style="color:var(--text2);margin-bottom:20px;font-size:0.92rem">
<strong>"Skill = 哲学 + 技术事实,不是操作手册。"</strong> 讲清 tradeoff 让 AI 自己选,不替它推理。
</p>
<div class="philosophy-steps">
<div class="step-card">
<span class="step-num">1</span>
<h4>拿到请求</h4>
<p>明确用户要做什么,定义成功标准:什么算完成?需要获取什么信息、达到什么结果?这是后续所有判断的锚点。</p>
</div>
<div class="step-card">
<span class="step-num">2</span>
<h4>选择起点</h4>
<p>根据任务性质、平台特征,选最可能直达的方式作为第一步去验证。需要登录态/动态页面 &rarr; 直接 CDP。</p>
</div>
<div class="step-card">
<span class="step-num">3</span>
<h4>过程校验</h4>
<p>每一步结果都是证据。对照成功标准更新判断。方向错了立即调整,不在同一方式上反复重试。</p>
</div>
<div class="step-card">
<span class="step-num">4</span>
<h4>完成判断</h4>
<p>对照成功标准确认完成后才停止。不为了"完整"而浪费代价,也不因为"差不多"而提前放弃。</p>
</div>
</div>
</section>
<!-- Comparison -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(239,68,68,0.15)">&#9878;</span>
对比web-access vs 现有工具
</h2>
<div class="compare-grid">
<div class="compare-card">
<span class="tag green">已有</span>
<h3>Claude Code 原生 + Playwright MCP + gptr</h3>
<ul style="list-style:none;padding:0;font-size:0.9rem;color:var(--text2)">
<li style="margin-bottom:6px">&#10003; WebSearch / WebFetch 基础联网</li>
<li style="margin-bottom:6px">&#10003; Playwright 完整浏览器自动化</li>
<li style="margin-bottom:6px">&#10003; gptr 深度调研出报告</li>
<li style="margin-bottom:6px">&#10007; 每次启动全新浏览器,无登录态</li>
<li style="margin-bottom:6px">&#10007; 需手动判断该用哪个工具</li>
<li>&#10007; 无站点经验积累</li>
</ul>
</div>
<div class="compare-card highlight">
<span class="tag purple">web-access 增量价值</span>
<h3>CDP 直连 + 策略调度 + 经验复用</h3>
<ul style="list-style:none;padding:0;font-size:0.9rem;color:var(--text2)">
<li style="margin-bottom:6px">&#9733; <strong>直连用户 Chrome 登录态</strong>(核心差异)</li>
<li style="margin-bottom:6px">&#9733; AI 自主选通道,无需手动指定</li>
<li style="margin-bottom:6px">&#9733; 站点经验跨 session 复用</li>
<li style="margin-bottom:6px">&#9733; 零外部依赖573 行代码</li>
<li style="margin-bottom:6px">&#9733; 子 Agent 并行分治</li>
<li>&#9733; 视频截帧分析能力</li>
</ul>
</div>
</div>
</section>
<!-- Code Highlight -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(168,85,247,0.15)">&lt;/&gt;</span>
技术亮点
</h2>
<div class="card-grid">
<div class="card">
<h3>&#128268; 零依赖设计</h3>
<p>整个 CDP Proxy 仅使用 Node.js 原生模块:<code>http</code><code>url</code><code>fs</code><code>net</code><code>os</code>
Node 22+ 的原生 WebSocket 替代了 <code>ws</code> 模块,做到真正零 <code>npm install</code></p>
</div>
<div class="card">
<h3>&#128270; 自动发现 Chrome 端口</h3>
<p>不需要用户手动指定端口。自动读取 <code>DevToolsActivePort</code> 文件获取端口和 WebSocket 路径,
支持 macOS / Linux / Windows 三平台。回退扫描 9222、9229、9333 常用端口。</p>
</div>
<div class="card">
<h3>&#128737; 防重复启动</h3>
<p>启动时先用 TCP 探测端口是否被占用。若已有实例运行且健康(<code>/health</code> 返回 ok静默退出。
避免多个 Proxy 实例冲突。</p>
</div>
<div class="card">
<h3>&#128200; 站点经验匹配</h3>
<p><code>match-site.sh</code> 读取用户输入,遍历 <code>site-patterns/*.md</code> 文件,
用域名 + aliases 做模式匹配,自动输出相关站点经验。跨会话积累,越用越聪明。</p>
</div>
</div>
<div class="code-block">
<span class="cmt">// cdp-proxy.mjs 核心连接逻辑(简化)</span><br>
<span class="kw">async function</span> <span class="fn">discoverChromePort</span>() {<br>
&nbsp;&nbsp;<span class="cmt">// 1. 读 DevToolsActivePort 文件获取端口</span><br>
&nbsp;&nbsp;<span class="kw">for</span> (<span class="kw">const</span> p <span class="kw">of</span> possiblePaths) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="kw">const</span> port = <span class="fn">parseInt</span>(fs.<span class="fn">readFileSync</span>(p));<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="kw">if</span> (<span class="kw">await</span> <span class="fn">checkPort</span>(port)) <span class="kw">return</span> { port, wsPath };<br>
&nbsp;&nbsp;}<br>
&nbsp;&nbsp;<span class="cmt">// 2. 回退扫描常用端口 [9222, 9229, 9333]</span><br>
}<br><br>
<span class="cmt">// HTTP API &rarr; CDP WebSocket &rarr; Chrome</span><br>
<span class="kw">function</span> <span class="fn">sendCDP</span>(method, params, sessionId) {<br>
&nbsp;&nbsp;ws.<span class="fn">send</span>(JSON.<span class="fn">stringify</span>({ id: ++cmdId, method, params, sessionId }));<br>
}
</div>
</section>
<!-- Verdict -->
<section>
<h2 class="section-title">
<span class="icon" style="background:rgba(108,92,231,0.15)">&#128203;</span>
评估结论
</h2>
<div class="verdict-box">
<h3>适合安装的场景</h3>
<ul>
<li>需要 Claude Code 操作<strong>已登录的网站</strong>(后台管理、社交平台、内部系统)</li>
<li>经常访问<strong>反爬严格的站点</strong>(小红书、微信公众号等)</li>
<li>希望联网操作<strong>更智能</strong>,不用手动选 WebFetch 还是 Playwright</li>
<li>需要<strong>视频截帧分析</strong>或复杂的浏览器交互</li>
</ul>
<h3 style="margin-top:16px">不需要安装的场景</h3>
<ul>
<li>现有 WebFetch + Playwright + gptr 已满足需求</li>
<li>不需要操作需登录的网站</li>
<li>主要做代码开发,联网需求少</li>
</ul>
<p style="margin-top:16px;padding:12px 16px;background:rgba(108,92,231,0.08);border-radius:8px;font-size:0.92rem">
<strong>核心价值:</strong>一句话总结 &mdash; web-access 的不可替代优势是<strong>直连用户 Chrome 登录态</strong>
其余能力搜索、抓取、浏览器操作在现有工具链中已有覆盖web-access 做的是<strong>更聪明的调度 + 更省心的体验</strong>
</p>
</div>
</section>
</div>
<footer>
<p>
源码仓库:<a href="https://github.com/eze-is/web-access" target="_blank">eze-is/web-access</a>
&nbsp;&middot;&nbsp; 作者:<a href="https://github.com/eze-is" target="_blank">一泽 Eze</a>
&nbsp;&middot;&nbsp; 许可证MIT
</p>
<p style="margin-top:8px;color:#555">研究存档 &middot; 2026-03-27</p>
</footer>
</body>
</html>