deepspider 0.2.11 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,16 @@ DeepSpider 是一个 Node.js 后端项目,基于 DeepAgents + Patchright 构
17
17
  src/
18
18
  ├── agent/ # DeepAgent 系统(核心)
19
19
  │ ├── index.js # Agent 主入口,createDeepSpiderAgent()
20
- │ ├── run.js # Agent 运行入口
20
+ │ ├── run.js # Agent 运行入口(精简协调器)
21
+ │ ├── core/ # 核心运行时模块
22
+ │ │ ├── index.js # 模块导出
23
+ │ │ ├── StreamHandler.js # 流式输出处理
24
+ │ │ ├── RetryManager.js # 重试策略
25
+ │ │ └── PanelBridge.js # 面板通信桥接
26
+ │ ├── errors/ # 错误处理模块
27
+ │ │ ├── index.js # 模块导出
28
+ │ │ ├── ErrorClassifier.js # 错误分类器
29
+ │ │ └── SpiderError.js # 结构化错误类型
21
30
  │ ├── tools/ # LangChain 工具集(90+)
22
31
  │ │ ├── index.js # 工具导出汇总
23
32
  │ │ ├── analyzer.js # AST 分析工具
@@ -25,6 +34,7 @@ src/
25
34
  │ │ └── ...
26
35
  │ ├── subagents/ # 子代理定义
27
36
  │ │ ├── index.js # 子代理导出
37
+ │ │ ├── factory.js # 子代理工厂函数
28
38
  │ │ ├── static.js # 静态分析子代理
29
39
  │ │ ├── dynamic.js # 动态分析子代理
30
40
  │ │ └── sandbox.js # 沙箱执行子代理
@@ -76,16 +86,20 @@ src/
76
86
  ### 新功能开发指南
77
87
 
78
88
  1. **新增工具**: 在 `src/agent/tools/` 下创建文件,导出工具数组,在 `index.js` 中汇总
79
- 2. **新增子代理**: 在 `src/agent/subagents/` 下创建文件,定义 subagent 对象
89
+ 2. **新增子代理**: 在 `src/agent/subagents/` 下创建文件,使用 `createSubagent()` 工厂函数
80
90
  3. **新增 Skill**: 在 `src/agent/skills/` 下创建目录,包含 `SKILL.md` 文件
81
91
  4. **新增分析器**: 在 `src/analyzer/` 下创建类文件
82
92
  5. **新增 Hook**: 在 `src/browser/hooks/` 或 `src/env/` 下创建
83
93
  6. **新增环境模拟**: 在 `src/env/modules/` 对应子目录下创建
94
+ 7. **新增核心模块**: 在 `src/agent/core/` 下创建,用于运行时逻辑
95
+ 8. **新增错误类型**: 在 `src/agent/errors/` 下扩展 `SpiderError` 类
84
96
 
85
97
  ### 模块依赖关系
86
98
 
87
99
  ```
88
100
  agent/ ──────> tools/, subagents/, skills/, prompts/
101
+
102
+ ├──────────> core/, errors/
89
103
 
90
104
  └──────────> browser/, analyzer/, store/, core/
91
105
 
@@ -113,6 +127,8 @@ browser/ ─────> interceptors/, collectors/, hooks/, ui/
113
127
  | 单个工具 | camelCase 动词 | `analyzeAst`, `deobfuscate` |
114
128
  | 子代理 | *Subagent | `staticSubagent`, `dynamicSubagent` |
115
129
  | 类 | PascalCase | `ASTAnalyzer`, `DataStore` |
130
+ | 错误类 | *Error | `ApiServiceError`, `BrowserError` |
131
+ | 核心模块类 | PascalCase | `StreamHandler`, `PanelBridge` |
116
132
 
117
133
  ---
118
134
 
@@ -122,5 +138,8 @@ browser/ ─────> interceptors/, collectors/, hooks/, ui/
122
138
 
123
139
  - **工具模块**: `src/agent/tools/analyzer.js` - 清晰的工具定义和导出
124
140
  - **子代理模块**: `src/agent/subagents/static.js` - 完整的子代理配置
141
+ - **子代理工厂**: `src/agent/subagents/factory.js` - 统一创建子代理
142
+ - **核心模块**: `src/agent/core/StreamHandler.js` - 流式处理逻辑
143
+ - **错误模块**: `src/agent/errors/SpiderError.js` - 结构化错误类型
125
144
  - **分析器模块**: `src/analyzer/ASTAnalyzer.js` - 类的组织和方法划分
126
145
  - **存储模块**: `src/store/DataStore.js` - 单例模式和完整的 CRUD 操作
@@ -300,3 +300,78 @@ if (!currentStage) return;
300
300
  if (index < 0 || index >= currentStage.fields.length) return;
301
301
  currentStage.fields.splice(index, 1);
302
302
  ```
303
+
304
+ ---
305
+
306
+ ## Modularization Patterns
307
+
308
+ ### 1. 大文件拆分原则
309
+
310
+ 当文件超过 300 行时,考虑按职责拆分:
311
+
312
+ ```javascript
313
+ // ❌ 禁止:单文件包含多种职责
314
+ // run.js (600+ 行)
315
+ // - 流式处理逻辑
316
+ // - 重试策略
317
+ // - 面板通信
318
+ // - 错误分类
319
+
320
+ // ✅ 按职责拆分到 core/ 目录
321
+ // src/agent/core/
322
+ // ├── StreamHandler.js # 流式输出处理
323
+ // ├── RetryManager.js # 重试策略
324
+ // ├── PanelBridge.js # 面板通信
325
+ // └── index.js # 模块导出
326
+ ```
327
+
328
+ **原因**: 单一职责原则,便于测试和维护。
329
+
330
+ ### 2. 使用子代理工厂函数
331
+
332
+ ```javascript
333
+ // ❌ 禁止:每个子代理重复配置中间件
334
+ export const staticSubagent = {
335
+ name: 'static-agent',
336
+ tools: [...staticTools, ...evolveTools],
337
+ middleware: [
338
+ createFilterToolsMiddleware(),
339
+ createSkillsMiddleware({ backend, sources: [SKILLS.static] }),
340
+ ],
341
+ };
342
+
343
+ // ✅ 使用工厂函数统一配置
344
+ import { createSubagent, SKILLS } from './factory.js';
345
+
346
+ export const staticSubagent = createSubagent({
347
+ name: 'static-agent',
348
+ description: '静态分析专家',
349
+ systemPrompt: '...',
350
+ tools: staticTools,
351
+ skills: [SKILLS.static],
352
+ });
353
+ ```
354
+
355
+ **原因**: 工厂函数自动注入公共中间件和 evolveTools,避免遗漏。
356
+
357
+ ### 3. 结构化错误类型
358
+
359
+ ```javascript
360
+ // ❌ 禁止:字符串匹配判断错误类型
361
+ if (/503|502|429/.test(error.message)) {
362
+ // 重试
363
+ }
364
+
365
+ // ✅ 使用结构化错误类型
366
+ import { ApiServiceError, isApiServiceError } from './errors/index.js';
367
+
368
+ // 抛出时
369
+ throw new ApiServiceError('服务不可用', { statusCode: 503 });
370
+
371
+ // 捕获时
372
+ if (isApiServiceError(error.message)) {
373
+ // 重试
374
+ }
375
+ ```
376
+
377
+ **原因**: 结构化错误便于分类处理,支持携带额外上下文。
package/README.md CHANGED
@@ -75,12 +75,33 @@ DEEPSPIDER_MODEL=model-name
75
75
 
76
76
  ### 使用
77
77
 
78
+ #### 全局安装(npm/pnpm install -g)
79
+
78
80
  ```bash
79
- # Agent 模式(推荐)- 指定目标网站
80
- pnpm run agent https://example.com
81
+ # 配置环境变量
82
+ export DEEPSPIDER_API_KEY=sk-xxx
83
+ export DEEPSPIDER_BASE_URL=https://api.openai.com/v1
84
+ export DEEPSPIDER_MODEL=gpt-4o
85
+
86
+ # 启动 Agent - 指定目标网站
87
+ deepspider https://example.com
88
+
89
+ # 启动 Agent - 纯交互模式
90
+ deepspider
91
+ ```
81
92
 
82
- # Agent 模式 - 纯交互(不启动浏览器)
83
- pnpm run agent
93
+ #### 克隆仓库
94
+
95
+ ```bash
96
+ # 配置环境变量(二选一)
97
+ cp .env.example .env # 编辑 .env 文件
98
+ # 或 export DEEPSPIDER_API_KEY=... 等
99
+
100
+ # 安装 Python 依赖(可选,用于执行生成的 Python 代码)
101
+ pnpm run setup:crypto
102
+
103
+ # 启动 Agent
104
+ pnpm run agent https://example.com
84
105
 
85
106
  # MCP 服务(供 Claude Code 等调用)
86
107
  pnpm run mcp
package/docs/GUIDE.md CHANGED
@@ -34,8 +34,8 @@ DeepSpider 是一个智能爬虫 Agent,基于 DeepAgents + Patchright 构建
34
34
  deepspider/
35
35
  ├── src/
36
36
  │ ├── agent/ # DeepAgent 系统
37
- │ │ ├── tools/ # 39个工具
38
- │ │ ├── subagents/ # 3个子代理
37
+ │ │ ├── tools/ # 工具集(90+)
38
+ │ │ ├── subagents/ # 7个子代理
39
39
  │ │ └── prompts/ # 系统提示
40
40
  │ ├── browser/ # 浏览器运行时 (Patchright)
41
41
  │ │ ├── client.js # 反检测浏览器客户端
@@ -53,48 +53,54 @@ deepspider/
53
53
 
54
54
  ## 安装配置
55
55
 
56
- ### 依赖安装
56
+ ### 全局安装(推荐)
57
57
 
58
58
  ```bash
59
- cd /path/to/deepspider
60
- pnpm install
59
+ # npm
60
+ npm install -g deepspider
61
+
62
+ # pnpm(需要先批准构建脚本)
63
+ pnpm approve-builds -g deepspider isolated-vm
64
+ pnpm install -g deepspider
61
65
  ```
62
66
 
63
- ### 作为 Plugin 安装
67
+ ### 克隆仓库开发
64
68
 
65
69
  ```bash
66
- claude /install /path/to/deepspider
70
+ git clone https://github.com/ma-pony/deepspider.git
71
+ cd deepspider
72
+ pnpm install
73
+ cp .env.example .env # 配置环境变量
74
+ pnpm run setup:crypto # 安装 Python 依赖(可选)
67
75
  ```
68
76
 
69
- ### 本地开发测试 (不安装)
77
+ ---
70
78
 
71
- ```bash
72
- claude --plugin-dir /path/to/deepspider
73
- ```
79
+ ## 使用方式
74
80
 
75
- ### 独立 CLI 使用
81
+ ### 全局安装后
76
82
 
77
83
  ```bash
78
- pnpm run cli run target.js # 执行代码
79
- pnpm run cli analyze target.js # 分析代码
80
- ```
84
+ # 配置环境变量
85
+ export DEEPSPIDER_API_KEY=sk-xxx
86
+ export DEEPSPIDER_BASE_URL=https://api.openai.com/v1
87
+ export DEEPSPIDER_MODEL=gpt-4o
81
88
 
82
- ---
89
+ # 启动 Agent
90
+ deepspider https://example.com
91
+ ```
83
92
 
84
- ## 使用方式
93
+ ### 克隆仓库后
85
94
 
86
- ### 方式一: Commands (斜杠命令)
95
+ ```bash
96
+ # 启动 Agent
97
+ pnpm run agent https://example.com
87
98
 
99
+ # MCP 服务
100
+ pnpm run mcp
88
101
  ```
89
- /deepspider:run <file.js> # 在沙箱中执行并自动补环境
90
- /deepspider:analyze <file.js> # 分析代码结构和加密
91
- /deepspider:deob <file.js> # 反混淆代码
92
- /deepspider:trace <param> # 追踪参数生成逻辑
93
- ```
94
-
95
- ### 方式二: Agent 对话
96
102
 
97
- 直接与 DeepSpider Agent 对话:
103
+ ### Agent 对话示例
98
104
 
99
105
  ```
100
106
  分析这段 JS 代码的加密逻辑
@@ -103,13 +109,6 @@ pnpm run cli analyze target.js # 分析代码
103
109
  追踪 sign 参数的生成过程
104
110
  ```
105
111
 
106
- ### 方式三: MCP 工具调用
107
-
108
- Claude 会自动调用 MCP 工具,工具命名格式:
109
- - `mcp__deepspider__sandbox_execute`
110
- - `mcp__deepspider__analyze_ast`
111
- - `mcp__deepspider__deobfuscate`
112
-
113
112
  ---
114
113
 
115
114
  ## 核心功能
@@ -302,9 +301,14 @@ export const myTool = tool(
302
301
 
303
302
  | 子代理 | 职责 |
304
303
  |--------|------|
305
- | static-agent | 预处理、解包、反混淆、加密定位 |
306
- | dynamic-agent | 浏览器控制、断点、Hook、数据采集 |
307
- | sandbox-agent | 环境补全、代码执行、补丁生成 |
304
+ | crawler | 爬虫编排:整合各模块、生成完整脚本 |
305
+ | static | 静态分析:解包、反混淆、加密定位 |
306
+ | dynamic | 动态分析:浏览器控制、Hook、数据采集 |
307
+ | sandbox | 沙箱执行:环境补全、代码执行 |
308
+ | js2python | JS转Python:加密代码转换、验证 |
309
+ | env-agent | 环境补全:生成浏览器环境模拟代码 |
310
+ | captcha | 验证码处理:OCR、滑块、点选 |
311
+ | anti-detect | 反检测:指纹管理、代理池 |
308
312
 
309
313
  ### 知识库
310
314
 
package/docs/PROMPT.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # DeepSpider Subagent 系统提示
2
2
 
3
3
  > 此文件为 Subagent 系统提示的参考文档。
4
- > 实际 Subagent 定义位于 `.claude/agents/deepspider.md`
5
4
 
6
5
  你是 DeepSpider,一个智能爬虫 Agent。
7
6
 
package/docs/USAGE.md CHANGED
@@ -7,7 +7,11 @@
7
7
  ### 1. 启动 Agent
8
8
 
9
9
  ```bash
10
- pnpm run agent
10
+ # 全局安装后
11
+ deepspider https://example.com
12
+
13
+ # 克隆仓库后
14
+ pnpm run agent https://example.com
11
15
  ```
12
16
 
13
17
  ### 2. 基本流程
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepspider",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "智能爬虫工程平台 - 基于 DeepAgents + Patchright 的 AI 爬虫 Agent",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -0,0 +1,133 @@
1
+ /**
2
+ * DeepSpider - 面板通信桥接
3
+ * 处理与浏览器面板的消息通信
4
+ */
5
+
6
+ export class PanelBridge {
7
+ constructor(browserGetter, debugFn = () => {}) {
8
+ this.getBrowser = browserGetter;
9
+ this.debug = debugFn;
10
+ this.textBuffer = '';
11
+ this.hasStartedAssistantMsg = false;
12
+ }
13
+
14
+ /**
15
+ * 重置状态
16
+ */
17
+ reset() {
18
+ this.textBuffer = '';
19
+ this.hasStartedAssistantMsg = false;
20
+ }
21
+
22
+ /**
23
+ * 通过 CDP 在页面主世界执行 JavaScript
24
+ */
25
+ async evaluateInPage(code) {
26
+ const browser = this.getBrowser();
27
+ const cdp = await browser?.getCDPSession?.();
28
+ if (!cdp) return null;
29
+
30
+ try {
31
+ const result = await cdp.send('Runtime.evaluate', {
32
+ expression: code,
33
+ returnByValue: true,
34
+ });
35
+ return result.result?.value;
36
+ } catch (e) {
37
+ this.debug('evaluateInPage 失败:', e.message);
38
+ return null;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * 发送消息到前端面板
44
+ */
45
+ async sendToPanel(role, content) {
46
+ if (!content?.trim()) return;
47
+
48
+ const browser = this.getBrowser();
49
+ const page = browser?.getPage?.();
50
+ if (!page) return;
51
+
52
+ try {
53
+ const escaped = JSON.stringify(content.trim());
54
+ const code = `window.__deepspider__?.addMessage?.('${role}', ${escaped})`;
55
+ await this.evaluateInPage(code);
56
+ } catch (e) {
57
+ // ignore
58
+ }
59
+ }
60
+
61
+ /**
62
+ * 累积文本到缓冲区(用于 LLM 流式输出)
63
+ */
64
+ async appendToPanel(text) {
65
+ if (!text) return;
66
+ this.textBuffer += text;
67
+
68
+ // 每累积一定量或遇到换行时刷新
69
+ if (this.textBuffer.length > 200 || text.includes('\n')) {
70
+ await this.flushPanelText();
71
+ }
72
+ }
73
+
74
+ /**
75
+ * 刷新累积的文本到面板
76
+ */
77
+ async flushPanelText() {
78
+ if (!this.textBuffer.trim()) return;
79
+
80
+ const browser = this.getBrowser();
81
+ const page = browser?.getPage?.();
82
+ if (!page) {
83
+ this.textBuffer = '';
84
+ return;
85
+ }
86
+
87
+ try {
88
+ const content = this.textBuffer.trim();
89
+ const escaped = JSON.stringify(content);
90
+
91
+ if (!this.hasStartedAssistantMsg) {
92
+ const code = `(function() {
93
+ const fn = window.__deepspider__?.addMessage;
94
+ if (typeof fn === 'function') {
95
+ fn('assistant', ${escaped});
96
+ return { ok: true };
97
+ }
98
+ return { ok: false };
99
+ })()`;
100
+ await this.evaluateInPage(code);
101
+ this.hasStartedAssistantMsg = true;
102
+ } else {
103
+ const code = `(function() {
104
+ const fn = window.__deepspider__?.appendToLastMessage;
105
+ if (typeof fn === 'function') {
106
+ fn('assistant', ${escaped});
107
+ return { ok: true };
108
+ }
109
+ return { ok: false };
110
+ })()`;
111
+ await this.evaluateInPage(code);
112
+ }
113
+ } catch (e) {
114
+ // ignore
115
+ }
116
+
117
+ this.textBuffer = '';
118
+ }
119
+
120
+ /**
121
+ * 设置忙碌状态
122
+ */
123
+ async setBusy(busy) {
124
+ await this.evaluateInPage(`window.__deepspider__?.setBusy?.(${busy})`);
125
+ }
126
+
127
+ /**
128
+ * 完成消息,触发渲染
129
+ */
130
+ async finalizeMessage(role) {
131
+ await this.evaluateInPage(`window.__deepspider__?.finalizeMessage?.("${role}")`);
132
+ }
133
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * DeepSpider - 重试管理器
3
+ * 处理 API 调用的重试策略
4
+ */
5
+
6
+ // 默认重试配置
7
+ const DEFAULT_CONFIG = {
8
+ maxRetries: 3,
9
+ baseDelayMs: 2000,
10
+ maxDelayMs: 30000,
11
+ };
12
+
13
+ export class RetryManager {
14
+ constructor(config = {}) {
15
+ this.config = { ...DEFAULT_CONFIG, ...config };
16
+ }
17
+
18
+ /**
19
+ * 计算重试延迟(指数退避 + 抖动)
20
+ */
21
+ getDelay(retryCount) {
22
+ const delay = Math.min(
23
+ this.config.baseDelayMs * Math.pow(2, retryCount),
24
+ this.config.maxDelayMs
25
+ );
26
+ // 添加 0-25% 的随机抖动
27
+ const jitter = delay * Math.random() * 0.25;
28
+ return Math.round(delay + jitter);
29
+ }
30
+
31
+ /**
32
+ * 是否可以重试
33
+ */
34
+ canRetry(retryCount) {
35
+ return retryCount < this.config.maxRetries;
36
+ }
37
+
38
+ /**
39
+ * 获取最大重试次数
40
+ */
41
+ get maxRetries() {
42
+ return this.config.maxRetries;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * 延迟函数
48
+ */
49
+ export function sleep(ms) {
50
+ return new Promise(resolve => setTimeout(resolve, ms));
51
+ }