crawlerkeeper-agent 1.0.0__tar.gz

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.
@@ -0,0 +1,16 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ .venv/
5
+
6
+ # 构建产物
7
+ dist/
8
+
9
+ # 运行时数据(本地部署产生,勿提交)
10
+ data/
11
+ logs/
12
+ agent.pid
13
+ .last_daemon_args
14
+
15
+ # 本地配置(含节点 Token,勿提交)
16
+ config/config.yaml
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CrawlerKeeper Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,377 @@
1
+ Metadata-Version: 2.5
2
+ Name: crawlerkeeper-agent
3
+ Version: 1.0.0
4
+ Summary: CrawlerKeeper 节点代理程序:节点注册、心跳上报、任务拉取与并行执行、部署同步与日志指标上报
5
+ Author: CrawlerKeeper Team
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: agent,crawler,crawlerkeeper,distributed,spider
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Internet :: WWW/HTTP
17
+ Classifier: Topic :: System :: Distributed Computing
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: prometheus-client>=0.17
20
+ Requires-Dist: psutil>=5.9.0
21
+ Requires-Dist: python-daemon>=3.0.0
22
+ Requires-Dist: pyyaml>=6.0
23
+ Requires-Dist: requests>=2.28.0
24
+ Description-Content-Type: text/markdown
25
+
26
+ # CrawlerKeeper Agent
27
+
28
+ 爬虫节点代理程序,负责与主控系统通信,执行爬虫任务。
29
+
30
+ > **部署与升级操作手册**:PyPI 发布、服务器部署、版本升级的完整 SOP 属团队内部文档,不随发布包公开。
31
+
32
+ ## 功能特性
33
+
34
+ - 节点自动注册
35
+ - 定时心跳上报(CPU/内存/磁盘)
36
+ - 任务自动拉取和执行
37
+ - **并行任务执行**:支持跨-Spider 并行,不同 Spider 的任务可同时执行
38
+ - **同一 Spider 串行**:通过 Semaphore 机制确保同一 Spider 的任务串行执行,避免冲突
39
+ - **容器资源感知**:根据容器 CPU 限制动态计算并发数
40
+ - **优雅关闭**:支持 SIGTERM/SIGINT 信号处理,任务排空不丢失
41
+ - 支持 Scrapy、Playwright、Selenium 爬虫框架
42
+ - 任务结果和日志上报
43
+ - YAML 配置文件支持
44
+ - 环境变量覆盖
45
+
46
+ ## 目录结构
47
+
48
+ ```
49
+ crawlerkeeper-agent/
50
+ ├── src/
51
+ │ ├── crawlerkeeper/
52
+ │ │ ├── __init__.py
53
+ │ │ ├── __main__.py # 命令行入口(pip 安装后的 crawlerkeeper-agent 命令)
54
+ │ │ ├── agent.py # 主程序
55
+ │ │ ├── config.py # 配置管理
56
+ │ │ ├── client.py # HTTP 客户端
57
+ │ │ ├── heartbeat.py # 心跳管理
58
+ │ │ ├── task.py # 任务管理
59
+ │ │ ├── executor.py # 爬虫执行器
60
+ │ │ └── logger.py # 日志管理
61
+ │ └── main.py # 本地源码运行入口
62
+ ├── config/
63
+ │ └── config.yaml # 配置文件
64
+ ├── pyproject.toml # 依赖声明 + PyPI 打包配置
65
+ ├── publish.sh # 构建 + 发布脚本
66
+ ├── bump_version.sh # 版本号管理
67
+ ├── run.sh # 本地启动脚本
68
+ └── sdk/
69
+ └── python/ # 爬虫 SDK(独立发包到 PyPI)
70
+ ├── crawlerkeeper_sdk/
71
+ ├── pyproject.toml
72
+ ├── publish.sh # 构建 + 发布脚本
73
+ └── migrate_spiders.py # 爬虫项目迁移脚本
74
+ ```
75
+
76
+ ## 快速开始
77
+
78
+ ### 1. 安装
79
+
80
+ ```bash
81
+ # 方式一:从 PyPI 安装(推荐,服务器部署用)
82
+ pip install crawlerkeeper-agent
83
+ # 或
84
+ uv tool install crawlerkeeper-agent
85
+
86
+ # 方式二:源码运行(本地开发用)
87
+ uv sync
88
+ ```
89
+
90
+ ### 2. 配置
91
+
92
+ 编辑 `config/config.yaml` 文件,配置主控系统地址:
93
+
94
+ ```yaml
95
+ server:
96
+ url: "http://localhost:8080" # 主控系统地址
97
+
98
+ agent:
99
+ name: "node-001" # 节点名称
100
+ ip: "" # 留空自动获取
101
+ port: 9000 # Agent 监听端口
102
+ registration_token: "" # 节点注册 Token(必填,从管理后台获取)
103
+
104
+ heartbeat:
105
+ interval: 30 # 心跳间隔(秒)
106
+
107
+ task:
108
+ poll_interval: 10 # 任务拉取间隔(秒)
109
+ work_dir: "./data/spiders" # 工作目录
110
+ # 最大并行任务数无需配置:默认按容器 CPU 自动计算,可用环境变量 AGENT_MAX_WORKERS 覆盖
111
+
112
+ logging:
113
+ level: "INFO"
114
+ file: "/var/log/agent.log"
115
+ ```
116
+
117
+ ### 3. 启动
118
+
119
+ ```bash
120
+ # PyPI 安装方式(命令行入口)
121
+ crawlerkeeper-agent -c config/config.yaml
122
+
123
+ # 或模块方式
124
+ python -m crawlerkeeper -c config/config.yaml
125
+
126
+ # 源码运行(本地开发)
127
+ python src/main.py -c config/config.yaml
128
+
129
+ # 或使用启动脚本
130
+ ./run.sh
131
+ ```
132
+
133
+ ### 4. 环境变量
134
+
135
+ 也可以使用环境变量覆盖配置文件:
136
+
137
+ | 变量名 | 说明 |
138
+ |--------|------|
139
+ | AGENT_SERVER_URL | 主控系统地址 |
140
+ | AGENT_API_KEY | API 密钥 |
141
+ | AGENT_NAME | 节点名称 |
142
+ | AGENT_IP | 节点 IP |
143
+ | AGENT_PORT | Agent 监听端口 |
144
+ | AGENT_REGISTRATION_TOKEN | 节点注册 Token(必填) |
145
+ | AGENT_HEARTBEAT_INTERVAL | 心跳间隔(秒) |
146
+ | AGENT_TASK_POLL_INTERVAL | 任务拉取间隔(秒) |
147
+ | AGENT_TASK_EXECUTE_TIMEOUT | 单个任务执行超时(秒),默认 3600;设为 0 表示不限时 |
148
+ | AGENT_WORK_DIR | 工作目录 |
149
+ | AGENT_MAX_WORKERS | 最大并行任务数(覆盖自动计算,范围 2-8,优先级最高) |
150
+ | CONTAINER_CPU_LIMIT | 容器 CPU 限制(如 "2000m" 或 "4"),自动计算 max_workers |
151
+ | AGENT_LOG_LEVEL | 日志级别 |
152
+ | AGENT_LOG_FILE | 日志文件 |
153
+
154
+ ## 部署到服务器(免手动上传)
155
+
156
+ 服务器上只需要 `run.sh` + `config/config.yaml` 两个东西,无需再手动上传安装包:
157
+
158
+ ```
159
+ /opt/crawlerkeeper-agent/
160
+ ├── run.sh
161
+ └── config/
162
+ └── config.yaml
163
+ ```
164
+
165
+ 启动命令与源码模式完全一致:
166
+
167
+ ```bash
168
+ ./run.sh --cleanup_temp_files=on --daemon=on start
169
+ ```
170
+
171
+ `run.sh` 会自动判断运行模式:
172
+
173
+ | 模式 | 判定条件 | 行为 |
174
+ |------|----------|------|
175
+ | 源码模式 | 脚本同目录存在 `src/main.py` | `uv sync` 后跑源码(本地开发) |
176
+ | 安装模式 | 脚本同目录没有源码 | 自动从 PyPI 安装 `crawlerkeeper-agent` 后运行(服务器部署) |
177
+
178
+ 安装模式下的安装策略:已安装则直接复用;未安装则依次尝试 `uv tool install` → `pip install --user` → `pip install`,
179
+ 装到 `~/.local/bin`(或 `uv tool` 的 bin 目录),失败时给出明确的手动安装命令。
180
+
181
+ 相关环境变量:
182
+
183
+ | 变量名 | 说明 |
184
+ |--------|------|
185
+ | AGENT_PACKAGE | 安装的包名/版本,默认 `crawlerkeeper-agent`;可写 `crawlerkeeper-agent==1.0.1` 锁定版本 |
186
+ | AGENT_AUTO_INSTALL | 设为 `off` 关闭自动安装(未安装时直接报错提示) |
187
+
188
+ ### 部署目录文件落位
189
+
190
+ 所有运行时文件都在 **run.sh 所在目录**(不会写进 site-packages 或其他位置):
191
+
192
+ | 路径 | 说明 | 源码模式 | 安装模式 |
193
+ |------|------|----------|----------|
194
+ | `config/config.yaml` | 主控地址、节点 Token 等配置(需自行提供) | 手动放置 | 手动放置 |
195
+ | `logs/agent.log` | 运行日志 | 自动创建 | 自动创建 |
196
+ | `agent.pid` | 进程 PID(供 stop/restart 使用) | 自动创建 | 自动创建 |
197
+ | `.last_daemon_args` | 后台启动参数记忆 | 自动创建 | 自动创建 |
198
+ | `data/` | 爬虫代码与任务工作目录 | 自动创建 | 自动创建 |
199
+ | `.venv/` | 源码模式的 Python 虚拟环境 | 自动创建(`uv sync`) | 不创建 |
200
+
201
+ 安装模式下 Agent 程序本体装在用户目录(`~/.local/bin` 或 `~/.local/share/uv/tools/`),不占部署目录。
202
+
203
+ ### 版本升级
204
+
205
+ > 完整的发布 SOP、首次部署步骤、常见问题属团队内部文档,不随发布包公开。
206
+
207
+ 发布新版本到 PyPI 后,服务器上一条命令完成升级(查 PyPI 最新版 → 对比本地版本 → 升级 → 自动重启):
208
+
209
+ ```bash
210
+ ./run.sh upgrade # 升级到 PyPI 最新版
211
+ ./run.sh upgrade 1.0.2 # 升级到指定版本
212
+ ```
213
+
214
+ 行为说明:
215
+
216
+ - 已是最新版本时不做任何操作,也不会重启 Agent(避免服务中断)
217
+ - 本地版本高于目标版本时跳过,不做降级
218
+ - 升级成功后自动重启(仅当 Agent 正在运行)
219
+ - `AGENT_UPGRADE_DRY_RUN=on` 可预演:打印将要执行的安装命令但不实际安装、不重启
220
+
221
+ ## 任务执行流程
222
+
223
+ 1. **注册节点** - 启动时向主控注册,获取节点 ID 和 API Key
224
+ 2. **心跳上报** - 定时上报节点资源状态
225
+ 3. **拉取任务** - 定时从主控获取待执行任务
226
+ 4. **同步代码** - 从主控下载爬虫文件
227
+ 5. **安装依赖** - 自动安装爬虫所需依赖
228
+ 6. **执行爬虫** - 在本地执行爬虫脚本(超过 `AGENT_TASK_EXECUTE_TIMEOUT` 秒未结束的进程会被终止:先 SIGTERM 宽限 10 秒,仍存活则 SIGKILL,任务按 FAILED/「执行超时」上报)
229
+ 7. **上报结果** - 上报任务执行结果和日志
230
+
231
+ > **存量长任务迁移提示**:默认超时 3600 秒(1 小时)。如有运行超过 1 小时的存量爬虫任务,
232
+ > 升级后会被超时终止,可在对应节点设置 `AGENT_TASK_EXECUTE_TIMEOUT=0` 关闭超时。
233
+
234
+ ## 并行任务执行
235
+
236
+ Agent 支持跨-Spider 并行执行任务,提高多爬虫场景下的资源利用率。
237
+
238
+ ### 三重去重机制
239
+
240
+ 为防止同一 Spider 任务被重复执行,Agent 实现了三重保险:
241
+
242
+ 1. **第一道防线(后端)**:后端根据 `excludeSpiderIds` 参数过滤,不返回已在执行的 Spider 的任务
243
+ 2. **第二道防线(Agent `_running_spiders`)**:Agent 侧维护运行中 Spider 列表,防止重复提交
244
+ 3. **第三道防线(Semaphore)**:每个 Spider 有独立的 Semaphore(1),确保同一 Spider 任务串行执行
245
+
246
+ ### 并发数计算
247
+
248
+ Agent 根据以下顺序确定最大并发数:
249
+
250
+ 1. **环境变量 `AGENT_MAX_WORKERS`**(优先级最高):直接指定,范围 [2, 8]
251
+ 2. **环境变量 `CONTAINER_CPU_LIMIT`**:K8s 注入的容器 CPU 限制
252
+ - 格式 `2000m` 表示 2 CPU
253
+ - 格式 `4` 表示 4 CPU
254
+ 3. **CPU 核心数**:`min(os.cpu_count(), 8)`,最小为 2
255
+
256
+ ### 容器环境变量注入(Kubernetes)
257
+
258
+ 在 K8s Pod 中通过 downward API 注入容器资源限制:
259
+
260
+ ```yaml
261
+ env:
262
+ - name: CONTAINER_CPU_LIMIT
263
+ valueFrom:
264
+ resourceFieldRef:
265
+ resource: limits.cpu
266
+ ```
267
+
268
+ ## 优雅关闭
269
+
270
+ Agent 支持 SIGTERM 和 SIGINT 信号,实现优雅关闭。
271
+
272
+ ### 信号处理
273
+
274
+ - **SIGTERM**:收到后进入 DRAINING 状态,停止接受新任务,等待运行中任务完成(最多 60 秒),然后退出
275
+ - **SIGINT (Ctrl+C)**:收到后立即进入 TERMINATING 状态,强制取消所有任务,然后退出
276
+
277
+ ### 关闭状态机
278
+
279
+ ```
280
+ RUNNING (正常)
281
+ │
282
+ │ stop(graceful=True) 或 SIGTERM
283
+ ▼
284
+ DRAINING (停止接受新任务,等待运行中任务完成)
285
+ │
286
+ │ 超时或 stop(graceful=False) 或 SIGINT
287
+ ▼
288
+ TERMINATING (强制取消未完成任务)
289
+ │
290
+ │ 所有任务完成
291
+ ▼
292
+ STOPPED (完全停止)
293
+ ```
294
+
295
+ ## 依赖要求
296
+
297
+ - Python 3.10+
298
+ - requests
299
+ - PyYAML
300
+ - psutil
301
+ - prometheus_client
302
+
303
+ ## 后端 API 对接
304
+
305
+ Agent 需要主控系统提供以下接口:
306
+
307
+ | 接口 | 方法 | 说明 |
308
+ |------|------|------|
309
+ | /api/nodes/register | POST | 节点注册 |
310
+ | /api/nodes/{id}/heartbeat | POST | 心跳上报 |
311
+ | /api/nodes/{id}/tasks/pending | GET | 拉取待执行任务 |
312
+ | /api/tasks/{id}/result | POST | 上报任务结果 |
313
+ | /api/tasks/{id}/logs | POST | 上报任务日志 |
314
+ | /api/spider-files/spider/{spiderId} | GET | 获取爬虫文件列表 |
315
+ | /api/spider-files/{fileId} | GET | 获取文件内容 |
316
+
317
+ ## Python SDK 发布
318
+
319
+ 爬虫业务代码使用的 SDK 位于 `sdk/python/`,以 `crawlerkeeper-sdk` 包名独立发布到公网 PyPI
320
+ (<https://pypi.org/project/crawlerkeeper-sdk/>),爬虫项目通过依赖声明引用,不再拷贝源码。
321
+
322
+ ```bash
323
+ cd sdk/python
324
+
325
+ # 仅构建(产物在 dist/)
326
+ ./publish.sh
327
+
328
+ # 发布预演(校验凭证与产物,不上传)
329
+ ./publish.sh --dry-run
330
+
331
+ # 构建并发布
332
+ ./publish.sh --publish
333
+ ```
334
+
335
+ 凭证来源(优先级从高到低):
336
+
337
+ 1. 环境变量 `PYPI_TOKEN`
338
+ 2. token 文件 `~/.pypi_token`(可用 `PYPI_TOKEN_FILE` 覆盖路径)
339
+
340
+ token 申请: <https://pypi.org/manage/account/token/>
341
+
342
+ - 版本号单一来源:`crawlerkeeper_sdk/__init__.py` 的 `__version__`
343
+ - 发布脚本内置品牌词闸门:待发布内容出现公司品牌词时直接中止
344
+ - 爬虫项目迁移说明见 `sdk/python/MIGRATION.md`
345
+
346
+ ## Agent 发布
347
+
348
+ Agent 本体以 `crawlerkeeper-agent` 包名发布到公网 PyPI
349
+ (<https://pypi.org/project/crawlerkeeper-agent/>),服务器直接 pip/uv 安装,
350
+ 无需手动上传安装包。
351
+
352
+ ```bash
353
+ # 仅构建(产物在 dist/)
354
+ ./publish.sh
355
+
356
+ # 发布预演(校验凭证与产物,不上传)
357
+ ./publish.sh --dry-run
358
+
359
+ # 构建并发布
360
+ ./publish.sh --publish
361
+ ```
362
+
363
+ 凭证来源(优先级从高到低):
364
+
365
+ 1. 环境变量 `PYPI_TOKEN`
366
+ 2. token 文件 `~/.pypi_token`(可用 `PYPI_TOKEN_FILE` 覆盖路径)
367
+
368
+ token 申请: <https://pypi.org/manage/account/token/>
369
+
370
+ - 版本号单一来源:`src/crawlerkeeper/__init__.py` 的 `__version__`(用 `bump_version.sh` 管理)
371
+ - sdist/wheel 走 include 白名单:只打包 `src/crawlerkeeper`、`tests`、`LICENSE`、`README.md`,
372
+ 内部资产(生产配置、Dockerfile、k8s 清单、demo、打包脚本)一律不进发布包
373
+ - 发布脚本内置品牌词闸门:待发布内容出现公司品牌词或内部域名时直接中止
374
+
375
+ ## License
376
+
377
+ MIT