内容
**简体中文** | [English](README.md)
# 章鱼侦察员
[](https://github.com/octoryn/octopus-scout/actions/workflows/ci.yml)
[](https://github.com/octoryn/octopus-scout/releases/latest)
[](LICENSE)
[](.nvmrc)
[](#存储)
章鱼侦察员是一种受管控、可审计、AI原生的网页、PDF和知识工作流摄取管道。
该首个版本针对80%的常规网页进行了优化:获取、可选的浏览器渲染、提取、规范化为Markdown/JSON、构建证据锚点、缓存/版本控制结果,并通过API、CLI、队列和MCP兼容的工具公开。
> 📐 **架构、技术笔记和Firecrawl比较**:参见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)。
## 快速开始
从npm安装(已发布软件包 — CLI、MCP服务器和库):
```bash
# 全局CLI
npm install -g octopus-scout
octopus-scout scrape https://example.com --render static
# 或在不安装的情况下运行
npx octopus-scout scrape https://example.com --render static
# 将MCP服务器连接到Claude Desktop / Claude Code
npx octopus-scout-mcp
```
> 从npm安装后,以`octopus-scout <command>`(或`npx octopus-scout <command>`)运行CLI;下面的`npm run cli -- <command>`形式是从源码运行的等价命令。
或从源码运行(用于开发):
```bash
npm install
npm run playwright:install
npm run dev
```
```bash
curl -s http://localhost:8787/health
curl -s http://localhost:8787/scrape \
-H 'content-type: application/json' \
-d '{"url":"https://example.com","render":"static"}'
```
> 🔒 SSRF防护默认阻止私有/环回主机 — 设置
> `OCTORYN_SCOUT_ALLOW_PRIVATE_HOSTS=true`以在本地开发和测试期间抓取`localhost`或其他私有地址。
CLI:
```bash
npm run cli -- scrape https://example.com --render static
npm run cli -- sitemap https://example.com/sitemap.xml
npm run cli -- map https://example.com --search docs --limit 100
npm run cli -- crawl https://example.com --max-depth 1 --max-pages 25
npm run cli -- export https://example.com --embed --jsonl
npm run cli -- ingest https://example.com
npm run cli -- search "what is this page about" --top-k 5 --mode hybrid
npm run cli -- extract https://example.com --schema '{"type":"object","properties":{"title":{"type":"string"}}}'
npm run cli -- ingest-site https://example.com --max-depth 1 --max-pages 25
npm run cli -- crawl https://example.com --resume <crawlId>
npm run cli -- crawls
npm run cli -- retention --snapshot-versions 5 --audit-days 90
npm run cli -- refresh --max-age-days 7
npm run cli -- approvals pending
npm run cli -- approve <approval-id> --by you@org.com --note "reviewed"
```
作为库使用:
该软件包(`octopus-scout`)通过其`dist/index.js`入口点公开引擎,
因此您可以直接调用管道而无需通过HTTP/CLI/MCP接口:
```ts
import { scrapeUrl, searchKnowledge } from "octopus-scout";
const result = await scrapeUrl({ url: "https://example.com", render: "static" });
console.log(result.extraction.markdown);
const hits = await searchKnowledge({ query: "what is this page about", topK: 5 });
console.log(hits);
```
### 存储
不需要Docker或外部数据库。默认情况下,章鱼侦察员使用嵌入式
**SQLite**数据库(单个`octopus-scout.db`文件位于数据目录下)用于快照、向量、审计、审批和爬取作业 — 克隆并运行。
> **适用于任何平台。** SQLite由可选的原生模块
> `better-sqlite3`提供;如果无法构建,`npm install`永远不会失败,并且在运行时
> 章鱼侦察员在驱动程序可用时使用SQLite,并在其他情况下透明地回退到文件后端(带一次性通知)。
> 所以克隆和运行的承诺即使在没有预构建二进制文件或构建工具链的情况下也成立。
- 设置`OCTORYN_SCOUT_STORAGE_BACKEND=file`以使用纯JSON回退(
`.octoryn-scout/`下的文件)。
- 设置`DATABASE_URL=postgres://...`以使用
**Postgres + pgvector**,适用于大型语料库或多实例部署。当设置`REDIS_URL`时,
`/jobs/scrape`和`npm run worker`使用BullMQ进行持久队列。
Postgres和Redis是完全可选的;仅在您超越嵌入式默认值时引入:
```bash
docker compose up
```
## API
摄取:
- `GET /health`
- `POST /fetch` 静态获取,带有机器人和速率限制策略
- `POST /render` Playwright浏览器渲染
- `POST /scrape` 完整摄取管道(哈希去重 + 管理门控;支持预抓取`actions`浏览器渲染)
- `POST /sitemap` 站点地图URL提取
- `POST /map` 快速站点URL发现(站点地图 + 根页面链接,相同来源/子域名 + 路径/搜索过滤器)— 参见Firecrawl `/map`
- `POST /crawl` 深度有界爬取(BFS,站点地图种子,相同来源 + 正则过滤器;`resumeCrawlId`继续检查点爬取)
- `GET /crawls` / `GET /crawls/:id` 列出/读取持久爬取作业
- `POST /jobs/scrape` / `POST /jobs/crawl` / `POST /jobs/ingest-site` 在配置Redis时,排队持久作业
- `GET /jobs/:id?queue=scrape|crawl|site|dead` 作业状态/结果/失败
知识和检索:
- `POST /export` 将页面分块并(可选)嵌入到RAG文档/JSONL中
- `POST /ingest` 抓取 → 分块 → 嵌入 → 存储到向量索引中
- `POST /ingest-site` 爬取整个站点并将每个页面索引到向量存储中
- `POST /search` 在知识库中检索 — `mode` = `vector` | `lexical` | `hybrid`(默认),可选`rerank`;返回带有引用锚点、信任和治理状态的块
- `POST /extract` LLM结构化提取 — 抓取URL并返回符合提供JSON模式的JSON
- `POST /extract/batch` 在显式URL列表上运行相同的JSON模式提取
- `POST /extract/site` 发现站点的URL(`/map`)并从每个页面提取模式
- `GET /extractions` 列出持久提取(受管控读取:默认情况下不包括`allowed`)
- `GET /extractions/:id` 通过ID读取持久提取
- `GET /versions?url=` URL版本历史(内容哈希快照)
- `GET /snapshots/:id` 读取保存的快照
治理和运营:
- `GET /governance/approvals?status=` 列出审批请求(待批/已批准/已拒绝)
- `GET /governance/approvals/:id` 读取审批请求
- `POST /governance/approvals/:id/decision` 批准/拒绝(记录审计事件)
- `GET /audit?target=&action=` 查询只读审计轨迹
- `POST /admin/retention` 清理旧快照版本、审计事件和已决审批
- `POST /admin/refresh` 运行陈旧度扫描 — 重新摄取超过阈值的快照
- `GET /events` 尾随最近内部事件(抓取/审批/爬取/摄取)
- `GET /webhooks` webhook交付日志(状态、尝试、响应代码)
- `GET /metrics` (`?format=prometheus`)请求/状态/治理计数器 + 每域统计
- `GET /ready` 就绪探测(检查配置的Redis/Postgres可达性)
## 管道
```text
URL输入
-> 获取器 / 浏览器渲染器(池化)/ 爬虫(深度有界BFS)
-> 内容提取器
-> Markdown / JSON 规范化器
-> 证据 + 引用构建器
-> 治理(信任评分、敏感域门控、审计、人工审批)
-> 缓存 / 哈希去重 / 版本控制
-> 知识管道(分块 + 嵌入钩子 + RAG/JSONL导出)
-> 代理 / RAG / 工作流(CLI、HTTP API、MCP服务器)
```
## 知识和RAG
`POST /export`(或`cli export`)将页面的Markdown按标题结构分成
标记边界的、重叠的块,将每个块映射回引用锚点和源Markdown中的字符偏移,
并发出`RagDocument`(或JSONL,一行一个块)。
`POST /ingest`运行完整的读取路径 — 抓取 → 分块 → 嵌入 → 存储 — 到向量索引中,
而`POST /search`检索查询的最近块,每个块携带其源URL、引用锚点、信任评分和治理状态。
受治理阻止的内容永远不会被索引;`requires_approval`内容被索引及其状态,以便搜索可以过滤它
(`includeBlocked`、`minTrust`、`url`)。
检索(`POST /search`)支持三种模式:`vector`(嵌入余弦)、
`lexical`(默认为SQLite FTS5,在文件后端为内存BM25,在Postgres上为Postgres全文检索),和
`hybrid`(默认)它用**互惠排名融合**融合两个候选集。
结果然后通过可插拔的重新排序器(`OCTORYN_SCOUT_RERANK_PROVIDER` =
`heuristic` 默认 | `cohere` | `voyage` | `none`);启发式重新排序器是确定性的和离线的,
而Cohere/Voyage在它们的API密钥被设置时激活。
可选的`rewrite`标志开启**启发式查询重写**:查询被扩展为一组确定性的、离线的变体
(原始、规范形式和无停用词关键词形式),每个变体被搜索和命中融合 — 无LLM调用,无密钥。
`POST /extract`(或`cli extract`)执行**LLM结构化提取**:它抓取一个
URL,然后返回符合您提供的JSON模式的JSON。提供者是可插拔的
(`OCTORYN_SCOUT_EXTRACTION_PROVIDER` = `none` 默认 | `anthropic` | `openai` | `bedrock`):
Anthropic使用官方SDK与`claude-opus-4-8`和`output_config` json-schema输出,
OpenAI使用json-schema `response_format`,而`bedrock`在**Amazon
Bedrock**上运行Anthropic模型,通过Bedrock API密钥(`AWS_BEARER_TOKEN_BEDROCK` + `OCTORYN_SCOUT_BEDROCK_REGION`,
强制工具使用JSON,无AWS SDK依赖);受治理阻止的页面被跳过,永远不会
提取。
提取还可以在单个页面之外进行扩展:`POST /extract/batch`在显式URL列表上运行相同的模式,
而`POST /extract/site`首先发现站点的URL(`/map`
路径)然后从每个页面提取模式 — 每个URL一个结果,单个失败
被捕获为跳过结果而不是中止运行。每个非阻塞结果都存储在**受管控的`ExtractionStore`**
(文件/SQLite/Postgres,完全像快照存储一样选择)及其`governanceStatus`;
`GET /extractions`和`GET /extractions/:id`
读取它们,默认情况下不包括非`allowed`行,可选择加入`includeUnapproved` —
与搜索相同的默认安全合约。
> 🔌 **框架集成**:要将受管控的检索读取路径插入
> LangChain或LlamaIndex,请参见 [docs/INTEGRATIONS.md](docs/INTEGRATIONS.md) —
> 框架无关的`searchAsDocuments`帮助程序和复制粘贴检索器
> 代码片段(章鱼侦察员不添加框架运行时依赖)。
嵌入通过可插拔的`EmbeddingProvider`
(`OCTORYN_SCOUT_EMBEDDING_PROVIDER` = `stub` | `voyage` | `openai`)生成:默认是一个
确定性的、无网络依赖的存根,而Voyage/OpenAI在它们的API密钥被设置时激活
(`VOYAGE_API_KEY` / `OPENAI_API_KEY`),否则回退到存根。
> ⚠️ **默认嵌入提供者是一个确定性的、非语义的存根** — 它
> 生成稳定的离线向量用于测试,但不捕获含义,因此`vector`
> 和`hybrid`搜索仅在您将`OCTORYN_SCOUT_EMBEDDING_PROVIDER`设置为`voyage`或`openai`(带有匹配的API密钥)时才有语义。向量
> 存储默认情况下是嵌入式**SQLite**后端(进程内余弦);
> 当设置`DATABASE_URL`时,它使用**pgvector**(`vector(dim)`列 + HNSW余弦索引,`<=>`距离)
> 并在`vector`扩展不可用时透明地回退到jsonb + 进程内余弦。
## 访问控制
设置`OCTORYN_SCOUT_AUTH_MODE`(`off` | `write` | `all`)和`OCTORYN_SCOUT_API_KEYS`
(逗号分隔)以通过`Authorization: Bearer <key>`或
`x-api-key`要求API密钥。`write`保护所有变更请求和治理敏感的
`/governance`和`/audit`读取;`all`保护除`GET /health`之外的所有内容。未配置任何密钥时,身份验证被禁用(向后兼容)。
## 每域策略
指向`OCTORYN_SCOUT_POLICY_FILE`(或放置`<dataDir>/policy.json`)一个
`GovernancePolicy`:每域`action`(`allow` | `block` | `require_approval`),
`rateLimitMs`和`trustOverride`。策略升级在关键字/机器人决策之上应用(它只能收紧,从不放松阻止),最具体的域匹配获胜。
```json
{
"version": "v1",
"defaultAction": "allow",
"domains": [{ "domain": "example.com", "action": "require_approval", "rateLimitMs": 3000 }]
}
```
## 扩展和可靠性
- **浏览器池** — 单个Chromium 实例,具有有限的并发页面
信号量(`OCTORYN_SCOUT_BROWSER_MAX_PAGES`)和空闲自动关闭。
- **分布式速率限制** — 通过Redis在多个进程之间强制执行每域间距,当设置`REDIS_URL`时
(原子EVAL),回退到内存中; 尊重机器人`crawl-delay`。
- **死信队列** — 抓取/爬取作业在重试次数耗尽后被推送到死信队列,并附带分类的失败原因
(`timeout`、`robots_blocked`、`http_error`、`render_error`、`unknown`)。
- **可恢复的爬取** — 爬取作业检查点它们的边界/访问结果/存储到
每个`OCTORYN_SCOUT_CRAWL_CHECKPOINT_EVERY`页的存储;`POST /crawl`与`resumeCrawlId`继续
从上一个检查点。`GET /crawls`列出作业。
- **整站摄取** — `POST /ingest-site` 爬取一个站点并将每个页面索引到向量存储中
通过一次调用;`POST /jobs/ingest-site` 以持久的 BullMQ 作业运行(轮询 `GET /jobs/:id`),
并将耗尽的重试路由到死信队列。
- **分布式调度器锁** — 调度成熟度扫描被 Redis 锁包裹
(`SET NX PX` + Lua 比较删除),因此多个实例不会重复扫描;
没有 Redis,它会降级为单实例任意运行。
- **保留** — `POST /admin/retention`(或`cli retention`)修剪旧快照版本、审计事件
和已决审批。`0` = 保留所有内容。
- **可观察性** — `GET /metrics`(JSON 或 Prometheus)和 `GET /ready`.
## 事件和自动化
引擎在内部事件总线上发出内部事件(`scrape.completed`、`approval.requested`、
`approval.decided`、`crawl.completed`、`site_ingest.completed`);`GET /events` 尾随它们。
- **Webhooks** — 设置`OCTORYN_SCOUT_WEBHOOK_URLS`(逗号列表)以将事件转发为
JSON POST。当设置`OCTORYN_SCOUT_WEBHOOK_SECRET`时,每个投递都带有
`x-octoryn-signature: sha256=<hmac>`标头用于验证;投递重试带有
回退直到`OCTORYN_SCOUT_WEBHOOK_MAX_ATTEMPTS`,并在`GET /webhooks`处记录。
使用`OCTORYN_SCOUT_WEBHOOK_EVENTS`过滤哪些事件触发。此功能关闭了
人在环中的回路:`approval.requested` webhook 可以呼叫审阅者。
- **调度刷新** — 启用`OCTORYN_SCOUT_SCHEDULE_ENABLED=true`后,背景扫描
每`OCTORYN_SCOUT_REFRESH_INTERVAL_MS`重新摄取旧快照
(至`OCTORYN_SCOUT_STALENESS_MAX_AGE_DAYS`),最多`OCTORYN_SCOUT_REFRESH_LIMIT`每次运行;
手动触发`POST /admin/refresh`或`cli refresh`.
## 发现和交互
- **`POST /map`** (或`cli map`)— 站点快速URL发现:从站点地图和
根页面链接播种,重复数据删除,按同源/子域名和`includePaths` /
`excludePaths` / `search`过滤,并限制在`limit`。
无需按URL抓取 — 这是一个廉价的地图。
- **预抓取动作** — `/scrape`和`/render`接受一个`actions`数组,在
捕获DOM之前按顺序在浏览器渲染中执行:`wait`、`waitForSelector`、`click`、
`scroll`、`type`、`press`、`screenshot`(每动作截图返回在
`actionScreenshots`)。适用于cookie横幅、“加载更多”和选项卡内容。
- **隐身增强** — `OCTORYN_SCOUT_STEALTH=true`渲染具有综合、手工制作
(零依赖)的反检测功能:现实的Chrome UA + UA-CH头部、本地时区/时区/视口、
自动化启动标志隐藏,以及一个初始化脚本,修补`navigator.webdriver`/
`languages`/`plugins`,伪造`window.chrome`,并伪造WebGL供应商/渲染器 +
`hardwareConcurrency`。`OCTORYN_SCOUT_EXTRA_HEADERS`(JSON)注入自定义
头部在静态获取和渲染路径上。
- **自带代理** — `OCTORYN_SCOUT_PROXY_URLS`(逗号列表,`http://user:pass@host:port`)
通过轮询旋转将请求路由到您的代理:Playwright原生渲染路径,和一个手工制作的
`node:net`/`node:tls` **CONNECT隧道**在静态路径上(零依赖)。自带代理 —
没有托管代理池。
- **JS挑战处理** — Cloudflare样式的“请稍候”中间页面被检测并等待
由真实浏览器执行挑战(无解答)。`FetchProvider`是一个可插拔的缝隙
(当前为`LocalFetchProvider`)用于未来后端。
- **CAPTCHA** — 存在`CaptchaSolver`缝隙但仅附带`NoopCaptchaSolver`
占位符(TODO)。解决现代CAPTCHA需要外部服务/模型,并且
故意不内置。
- **范围外(按设计)**:托管代理池和对抗性反机器人逃避。
隐身 + 自带代理 + 挑战等待处理大多数日常网络;
具有主动机器人防御或CAPTCHA的困难目标不受保证。
## 安全
- **SSRF保护** — 每次外部获取/渲染都经过一个URL守卫,该守卫拒绝非`http(s)`协议的请求,以及任何解析为私有/环回/本地链接地址的主机(包括云元数据IP `169.254.169.254`),通过检查解析后的IP地址来防止DNS重绑定。可以通过设置`OCTORYN_SCOUT_ALLOW_PRIVATE_HOSTS=true`(用于本地开发/测试)或使用`OCTORYN_SCOUT_HOST_ALLOWLIST` / `_BLOCKLIST`来覆盖每个环境。
- **内容限制** — 超过`OCTORYN_SCOUT_MAX_CONTENT_BYTES`的响应将被拒绝(流式读取会提前中止),并且只处理`OCTORYN_SCOUT_ALLOWED_CONTENT_TYPES`类型的内容;响应体将从内容类型头部进行字符集解码。
- **API密钥认证** — 参见上面的访问控制;`/governance`、`/audit`和`/admin`的读取/写入操作在`write`模式下受到保护。
## MCP服务器(Claude & Codex)
该引擎自带一个MCP标准输入/输出服务器,暴露了八种工具 — `octoryn_scrape`、`octoryn_crawl`、`octoryn_map`、`octoryn_export`、`octoryn_ingest`、`octoryn_ingest_site`、`octoryn_search`、`octoryn_extract` — 允许代理进行抓取、爬取、映射、摄入、**对受管知识库进行语义搜索**,以及运行结构化提取。
```bash
npm run build # 生成 dist/mcp.js
npx octopus-scout-mcp # 或:node dist/mcp.js
```
可直接粘贴的配置文件位于[`docs/mcp/`](docs/mcp/)(Claude Code `.mcp.json`,Claude Desktop,Codex `config.toml`);完整指南请参见[docs/MCP.md](docs/MCP.md)。
## 治理默认值
该引擎默认尊重`robots.txt`,应用每个域的速率限制,记录内容哈希和源元数据,从提取的Markdown创建引用锚点,并分配一个基本的源信任分数。
医疗/法律/财务内容被标记为`requires_approval`:创建一个待处理的`ApprovalRecord`,页面等待通过`/governance/approvals/:id/decision`(或`cli approve/reject`)的人工决策。每次抓取、审批请求和决策都会被写入一个只追加的**审计轨迹**(`/audit`)。`OCTORYN_SCOUT_APPROVAL_MODE`(`off` | `flag` | `enforce`)控制门控的严格程度。
通过内容哈希对未更改内容的重新抓取进行**去重**,每个不同的版本保留为一个可查询的快照(`/versions?url=`)。
这些策略有意为保守,易于替换为更严格的Octoryn治理规则。
## 贡献
参见 [CONTRIBUTING.md](CONTRIBUTING.md) 进行设置和本地检查门控(`typecheck` + `format:check` + `test`)。安全问题:请遵循 [SECURITY.md](SECURITY.md) 而不是公开提出问题。
## License
[AGPL-3.0-or-later](LICENSE) © Octoryn. 网络使用即为分发:如果您运行修改后的版本作为服务,AGPL要求您向用户提供修改后的源代码。这是有意的 — 它保持引擎及其衍生品的开放。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器