多数据源聚合采集实现方法详解(不同数据源对接方式)

多数据源采集的核心是把异构的抓取方式收敛成统一的接口:有官方 API 的源走 HTTP 请求拿 JSON,没有 API 的源用 Axios 抓 HTML 再交给 Cheerio 解析,内容源则走 RSS 订阅。三种方式在项目里对应三个 Collector 实现类,对外暴露同一套 fetch + parse 契约,采集调度器只依赖接口,不关心每个源内部怎么拿数据。聚合层负责把不同源的同一条内容用 URL 哈希去重、按热度权重合并排序,再由 AI 分析层做相关性评分。这套设计让项目后续新增小红书、掘金等源时,只写一个实现文件加一段配置,核心代码零改动。

一、三种数据源接入方式

1.1 官方 API 接入

有稳定公开接口的源优先走 API。Hacker News 直接打 Algolia 搜索接口,按热度排序取 top 条目;B 站公开接口做视频搜索;Twitter 走 TwitterAPI.io 的付费 API 做高级搜索。API 源数据结构干净,返回 JSON,解析成本低、稳定性也好。

const res = await axios.get('https://hn.algolia.com/api/v1/search', {
  params: { tags: 'front_page', hitsPerPage: 50 },
});
const items = res.data.hits
  .sort((a, b) => b.points - a.points)
  .map((h) => ({
    title: h.title,
    url: h.url || `https://news.ycombinator.com/item?id=${h.objectID}`,
    score: h.points,
    publishedAt: new Date(h.created_at),
  }));

1.2 网页爬虫接入

GitHub Trending 没有官方 API,只能抓取页面解析 HTML。用 Cheerio 选择仓库列表节点,提取仓库名、描述、编程语言、star 数。搜索引擎类源(Bing、搜狗)同样走爬虫,抓搜索结果页。爬虫源最大的风险是目标站改版,选择器一旦失效整条链就断了,所以爬虫源被安全兜底包裹,解析失败时这一路返回空数组而不是抛出异常拖垮整轮任务。

const html = await axios.get('https://github.com/trending', {
  headers: { 'User-Agent': UA_POOL[Math.floor(Math.random() * UA_POOL.length)] },
});
const $ = cheerio.load(html);
$('article h2 a').each((_, el) => {
  const repo = $(el).attr('href').trim();
  result.push({ title: repo, url: `https://github.com${repo}` });
});

1.3 RSS 订阅接入

中文科技媒体如少数派有原生 RSS,36 氪、虎嗅等没有公开接口的走 RSSHub 中转。RSS 源解析用统一的 feed 解析库,提取 title、link、pubDate。踩过的真实教训是 RSSHub 公共实例经常没数据或限流,上线前把依赖公共实例的源直接停用,改为自建实例后再接入。

1.4 三种方式对比

维度 官方 API 网页爬虫 RSS 订阅
数据格式 JSON,结构清晰 HTML,需解析 XML,规则统一
稳定性 高,接口有契约 低,改版即失效 中,依赖源是否维护
访问限制 常有速率限制 需控频率防封 低频抓取较宽松
解析成本 低 高,选择器易碎 低
典型源 HN、B 站、Twitter GitHub Trending、Bing 少数派、36 氪、虎嗅

二、Collector 抽象与配置化

每个数据源实现同一个接口,采集调度器只认识接口不认具体源。

interface Collector {
  source: string;              // 唯一标识
  fetch(): Promise<RawItem[]>; // 抓取原始数据
  parse(raw: unknown): RawItem[]; // 转成统一结构
}

const registry: Record<string, Collector> = {
  hackernews: new HackerNewsCollector(),
  githubTrending: new GithubTrendingCollector(),
  sspai: new RssCollector('https://sspai.com/feed'),
  // 新增源:写一个实现类,注册进来即可
};

配置化体现在源表驱动:每个源在配置里定义是否启用、抓取间隔、超时时间、单次上限。调度器遍历启用的源并行发起抓取,公共的限速、UA、重试逻辑抽成中间件统一套用,单个源故障只记录日志并跳过,不影响其他源。

三、聚合层的去重与合并

聚合分三步走:

  1. 对每条结果的 URL 做规范化(去锚点、去追踪参数、统一协议头);
  2. 取 MD5 生成唯一键,用数据库唯一约束拦截重复插入;
  3. 命中关键词的条目进入候选集,按源质量加权后交给 AI 分析。

数据源质量分级是聚合层的另一层筛选:arXiv、Hacker News 这类高质量源直接进入候选集,微博、搜索引擎结果这类噪音大的源需要 AI 二次验证才放行。无 AI Key 时降级到启发式模式,按热度阈值和关键词精确匹配粗筛。

四、调度与容错的工程细节

定时任务用 node-cron 驱动,默认 30 分钟一轮,热榜类源单独缩短间隔。容错覆盖四层:请求超时统一 10 秒;失败重试三次且指数退避;数据源级熔断,连续失败超过阈值暂停该源;解析异常只丢弃当前条目。整个采集层最看重的一点是”任何单点故障都不能拖垮整轮”,所有外部依赖都有兜底。

常见问题(FAQ)

Q1:网页爬虫被反爬怎么办?

轮换 UA、控制抓取频率、加代理池;严重受限的源改走第三方聚合接口。

Q2:同一内容被多个源抓到怎么去重?

URL 规范化后取 MD5 建唯一索引,数据库层拦截重复插入。

Q3:新增一个数据源要改多少代码?

只写一个实现 Collector 的类并注册,调度、去重、分析逻辑全部自动生效。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
蓝队管理员的头像蓝队管理员普通用户

相关推荐

返回顶部