🕷️
🕷️

Auto Collection

  • 利用 Puppeteer 自动巡检各大主流科技网站。

  • 让 AI 助手替代人工,从繁琐的信息搜索中解脱。

Slide 1 of 3Remaining 2

前言

“哎,新款 Pixel 的发售日是什么时候来着?” “忘了报名这场科技大会了……”

如果你是个数码爱好者,一定有过这种烦恼。信息散落在 Twitter (X)、PR Times 和各种新闻网站上,光是追踪这些信息就很费劲。

作者
作者

靠自己检查所有信息是不可能的。那么,交给 AI 去做不就好了吗?

于是,我制作了一个 “最强数码日历”——它能自动收集网页上的活动信息,进行整齐的分类,并顺便展示我写的相关博客文章

今天,我将通过代码带大家深度解析其背后的技术原理。

成果展示:这就是“AI 数码日历”

首先请看成品。该功能已实现在本站的 /calendar 页面。

本次开发的亮点包括:

核心功能
  • 全自动收集 :一条指令即可巡检主要科技媒体。 * AI 自动分类 :AI 自动判别“新机发布”、“大会”、“促销”等类别。 * 博客整合 :我自己写的评测文章也会展示在同一条时间线上。 * 高级 UI :采用毛玻璃(Glassmorphism)设计,满足极致的审美追求。

技术栈:AI 时代的 Web 开发

为了实现这个日历,我选择了以下技术组合:

  1. Astro DB :数据的母舰。基于 SQL (LibSQL),无论在本地还是线上环境中都极速响应。
  2. Puppeteer :负责网页抓取。即使是动态渲染的网站也能精准提取信息。
  3. Vercel AI SDK :大脑担当。让 GPT-4o 从抓取到的杂乱 HTML 中提取出核心信息。
  4. React + Framer Motion :UI 担当。将 React 组件挂载到 Astro 中,实现丰富的交互效果。

实现细节

1. 利用 AI 智能体收集信息

最核心的难点在于“如何从混乱的网页文本中准确提取活动信息”。 这正是 Vercel AI SDK 大显身手的地方。

以下是实际使用的脚本(scripts/collect-events.ts)的部分代码:

// 将抓取到的原始内容交给 AI,让其返回结构化数据
const { text } = await generateText({
 model: "openai('gpt-4o')",
 prompt: "`Extract upcoming tech/gadget events from the following text.
 For each event", provide: "title", date (YYYY-MM-DD), category (e.g., "Release", "Conference", "Sale"), description, and sourceUrl.
 Return as a JSON array of objects.
 Text: "${rawContent"}`,
});
Assistant
Assistant

如果使用传统的正则表达式或 CSS 选择器,每当网站结构变化时都需要修改代码。但 LLM 可以理解“文本的含义”来提取日期和标题,极大地降低了维护成本。

2. 保存至 Astro DB

提取出的数据会保存到 Astro DB 中。其模式定义(db/config.ts)非常直观:

export const Events = defineTable({
 columns: {
 id: column.text({ primaryKey: true }),
 title: column.text(),
 date: column.date(),
 category: column.text(),
 sourceUrl: column.text({ optional: true }),
 // ...
 },
});

之后只需通过 await db.insert(Events).values(...) 存入即可。无需配置 ORM,也无需手动管理迁移文件。Astro 体验极佳。

3. 与博客文章整合

该日历的精髓在于 “外部活动信息”与“个人博客文章”的完美交织

我们在 src/pages/calendar/index.astro 中对这两类数据进行合并:

// 1. 获取抓取的活动
const scrapedEvents = await db.select().from(Events);

// 2. 获取博客文章
const blogPosts = await getCollection("blog");

// 3. 将两者规范化为“Event”类型并合并
const allEvents = [
 ...scrapedEvents.map((e) => ({ ...e, type: "scraped" })),
 ...blogPosts.map((p) => ({
 title: "p.data.title",
 date: "p.data.date",
 type: "blog",
 })),
];

通过将数据传递给 React 组件 <CalendarContainer /> ,我们实现了无缝的时间轴展示。

总结:网站从“媒体”向“工具”的进化

纯粹发布信息的静态博客可能已经过时了。

让智能体在后台运行,为用户搜集、整理信息并展示——通过结合 Astro DBAI SDK ,个人开发者也能轻松构建出这样“有生命的网站”。

📝 后续规划

接下来,我计划实现一个功能:用户可以收藏感兴趣的活动,并在活动前一天通过 Discord 收到提醒。敬请期待!

您可以随时通过右上角菜单或 /calendar 访问该日历。希望能为您的科技数码生活增添一份秩序与节奏感。