亮点URL 去重技术
URL 去重技术
智能 URL 去重机制:避免重复抓取、节省成本、保留内容版本历史。OctoReport 的核心技术优势之一。
智能 URL 去重机制,避免重复抓取、节省成本、保留内容版本历史。这是 OctoReport 的核心技术优势之一。
💡 核心价值:URL 去重可节省 70-90% 的重复抓取成本,同时保证数据的准确性和一致性。
1. 为什么需要URL去重
1.1 问题场景
场景 1:RSS 订阅源每天执行
- RSS Feed 返回最新 20 条文章
- 第一天收集 20 条(全部新内容)
- 第二天收集 20 条(其中 18 条是昨天已收集的)
- 问题:如果不去重,会重复抓取相同 URL 的内容,浪费 18 次 API 调用
场景 2:搜索源定期执行
- 关键词:"AI 大模型"
- 每 6 小时执行一次
- 很多热门文章会重复出现在搜索结果中
- 问题:如果不去重,相同文章会被多次抓取并保存多个副本
1.2 不去重的后果
| 后果 | 影响 | 成本增加 |
|---|---|---|
| 重复抓取 | 浪费 API 调用(Firecrawl、Browserless) | 10-50 credits/次 |
| 重复清洗 | 浪费 LLM token | 10-20 credits/次 |
| 数据冗余 | 相同内容保存多个副本 | 数据库膨胀 |
| 报告质量下降 | 报告中出现重复内容 | 用户体验差 |
成本对比示例:
场景:RSS 订阅源,每天执行,每次返回 20 条
不去重成本(每天):
- 第1天:20条 × 2 credits = 40 credits
- 第2天:20条 × 2 credits = 40 credits(其中 18 条重复)
- 第3天:20条 × 2 credits = 40 credits(其中 18 条重复)
- 总计:120 credits/3天 = 40 credits/天
去重成本(每天,使用 KEEP_OLD):
- 第1天:20条 × 2 credits = 40 credits
- 第2天:2条 × 2 credits = 4 credits(跳过 18 条已存在)
- 第3天:2条 × 2 credits = 4 credits(跳过 18 条已存在)
- 总计:48 credits/3天 = 16 credits/天
节省比例:(40 - 16) / 40 = 60%2. 去重策略详解
OctoReport 提供两种去重策略,适用于不同场景。
2.1 UPDATE 策略(默认)
工作原理:
- 发现新 URL → 直接抓取并保存
- 发现重复 URL + 抓取成功 → 标记旧内容为"已过期",保存新版本
- 发现重复 URL + 抓取失败 → 更新旧内容的采集时间,不保存新内容
适用场景:
- ✅ 内容会更新(如商品价格、库存信息、新闻更正)
- ✅ 需要保留历史版本(审计、对比分析)
- ✅ 愿意支付更新成本(重新抓取需要消耗 API 调用)
优势:
- 始终获取最新版本
- 保留历史版本(旧内容标记为"已过期"但不删除)
- 抓取失败时保留旧内容(容错机制)
成本:
- 每次重复 URL 都会重新抓取
- 成本较高(但保证数据最新)
2.2 KEEP_OLD 策略
工作原理:
- 发现新 URL → 抓取并保存
- 发现重复 URL → 直接跳过(不抓取、不保存),只更新旧内容的采集时间
适用场景:
- ✅ 内容不会更新(如新闻文章、RSS Feed、历史文档)
- ✅ 只关心新增内容(不关心已收集内容的更新)
- ✅ 成本敏感(希望节省 API 调用)
优势:
- 避免重复抓取(节省 70-90% 成本)
- 执行速度更快(无需等待重复 URL 的抓取)
- 适合大量 URL 的场景(如 RSS Feed、新闻源)
注意事项:
- ⚠️ 如果内容确实更新了,也不会重新抓取
- ⚠️ 无法获取内容的最新版本
2.3 两种策略对比
| 特性 | UPDATE(默认) | KEEP_OLD |
|---|---|---|
| 重复URL处理 | 重新抓取 | 跳过抓取 |
| 内容版本 | 保留所有版本(旧版本标记过期) | 只保留首次版本 |
| 成本 | 高(每次都抓取) | 低(只抓取新URL) |
| 速度 | 慢(需等待抓取) | 快(跳过抓取) |
| 适用场景 | 内容会更新 | 内容不会更新 |
| 推荐指数 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐(RSS/新闻) |
3. 去重时间线示例
3.1 UPDATE 策略示例
场景:监控商品价格(需要获取最新价格)
时间线:
第1天 9:00 - 首次收集
• URL: https://example.com/product/123
• 价格: ¥99
• 操作: 保存内容 A
• 成本: 10 credits
第2天 9:00 - 第二次收集
• URL: https://example.com/product/123(重复)
• 价格: ¥89(降价了!)
• 操作:
1. 重新抓取(成功)
2. 标记内容 A 为"已过期"
3. 保存内容 B(新版本)
• 成本: 10 credits
第3天 9:00 - 第三次收集
• URL: https://example.com/product/123(重复)
• 抓取失败(网站维护)
• 操作:
1. 尝试抓取(失败)
2. 更新内容 B 的采集时间
3. 不保存新内容
• 成本: 0 credits(抓取失败不计费)
结果:
• 知识库中有 2 条内容(A 已过期,B 未过期)
• 报告生成时只使用内容 B(最新价格 ¥89)
• 可查看历史版本(内容 A,价格 ¥99)3.2 KEEP_OLD 策略示例
场景:订阅新闻 RSS(内容不会更新)
时间线:
第1天 9:00 - 首次收集
• RSS 返回 20 条文章
• 全部新 URL
• 操作: 保存 20 条内容
• 成本: 20 × 2 credits = 40 credits
第2天 9:00 - 第二次收集
• RSS 返回 20 条文章
- 18 条是昨天的(重复)
- 2 条是新文章
• 操作:
1. 检测到 18 条重复 URL
2. 跳过这 18 条(不抓取)
3. 只抓取 2 条新文章
4. 更新旧 18 条的采集时间
• 成本: 2 × 2 credits = 4 credits
第3天 9:00 - 第三次收集
• RSS 返回 20 条文章
- 18 条是前天的
- 2 条是昨天的
- 0 条是新文章
• 操作:
1. 检测到 20 条重复 URL
2. 全部跳过(不抓取)
3. 更新这 20 条的采集时间
• 成本: 0 credits
结果:
• 知识库中有 20 条内容(全部未过期)
• 3天总成本: 44 credits
• 如果使用 UPDATE: 120 credits
• 节省: 63%4. 技术实现细节
4.1 URL 唯一性识别
识别方式:
- 使用完整 URL 作为唯一标识
- URL 格式化(移除 trailing slash、统一协议)
- 数据库索引优化(快速查询重复 URL)
特殊处理:
- 查询参数:
?utm_source=xxx等跟踪参数会被保留(不同参数视为不同 URL) - Fragment:
#section锚点会被移除(视为相同 URL) - 大小写:不敏感(
Example.com和example.com视为相同)
4.2 版本管理机制
内容字段:
isExpired: 是否过期(boolean)expiredAt: 过期时间(timestamp)collectedAt: 最后采集时间(timestamp)
版本管理流程:
- 检测重复:根据 URL 查询数据库
- 标记过期(UPDATE 策略):设置
isExpired=true,expiredAt=now - 保存新版本:创建新记录,
isExpired=false - 报告过滤:查询时自动过滤
isExpired=true的内容
4.3 性能优化
批量检测:
- 一次查询检测多个 URL(减少数据库往返)
- 使用
IN查询(而非逐个查询)
索引优化:
sourceUrl字段添加索引isExpired字段添加索引- 组合索引:
(sourceId, sourceUrl, isExpired)
并发控制:
- 使用数据库事务(避免竞态条件)
- 乐观锁机制(版本号控制)
5. 实际应用建议
5.1 如何选择策略
决策树:
问自己:这个 URL 的内容会更新吗?
会更新
├─ 价格、库存、评分等 → 使用 UPDATE
├─ 新闻更正、文章修订 → 使用 UPDATE
└─ 需要保留历史版本 → 使用 UPDATE
不会更新
├─ RSS Feed 文章 → 使用 KEEP_OLD ⭐
├─ 社交媒体帖子 → 使用 KEEP_OLD ⭐
├─ 历史文档、存档 → 使用 KEEP_OLD ⭐
└─ 新闻发布(固定内容) → 使用 KEEP_OLD ⭐
不确定
└─ 先用 UPDATE,观察几天后调整5.2 策略切换
如何切换:
- 编辑数据源配置
- 修改
update_strategy字段(UPDATE或KEEP_OLD) - 保存配置
- 下次执行时生效
切换影响:
- UPDATE → KEEP_OLD:后续不再重新抓取已存在的 URL(成本降低)
- KEEP_OLD → UPDATE:后续会重新抓取所有 URL(包括已存在的)
- 已保存的内容:不受影响(策略只影响后续执行)
5.3 查看去重效果
任务日志:
- 查看"任务日志"(侧边栏 → 任务日志)
- 查看数据源任务的
message字段 - 显示:"发现 X 个新 URL,跳过 Y 个已存在 URL"
内容库:
- 查看知识库内容(知识库管理 → 查看内容)
- 筛选"已过期"内容(如果使用 UPDATE 策略)
- 对比不同版本的内容
6. 常见问题
Q1: KEEP_OLD 策略会完全跳过重复 URL 吗?
A:是的。使用 KEEP_OLD 策略时,重复的 URL 会被完全跳过(不抓取、不保存),只更新旧内容的 collectedAt 时间戳。这样可以大幅降低成本。
Q2: UPDATE 策略会保留所有历史版本吗?
A:是的。旧版本会被标记为"已过期"(isExpired=true),但不会被删除。你可以在内容库中筛选"已过期"内容,查看历史版本。
Q3: 如何清理已过期的内容?
A:目前系统不会自动清理已过期的内容。如果需要清理,可以:
- 在内容库中手动删除已过期的内容
- 联系管理员执行批量清理(慎用,不可恢复)
Q4: RSS 订阅源应该使用哪种策略?
A:强烈推荐使用 KEEP_OLD 策略。理由:
- RSS Feed 的文章内容通常不会更新
- 只需要获取新发布的文章
- 可节省 70-90% 的成本
Q5: 去重是基于整个 URL 还是只基于域名?
A:基于完整 URL(包括路径和查询参数)。例如:
https://example.com/page?id=1和https://example.com/page?id=2被视为不同 URLhttps://example.com/page和https://example.com/page/被视为相同 URL(移除 trailing slash)