《NestJS智能体开发》(六):网站内容抓取为知识库数据

为了让智能体能够更精准地决策,我们需要为它构建一个专业知识库,本文将探讨 NestJS 中结合 PlaywrightTurndown 等工具,实现对网站内容的抓取,并将其转换为Markdown数据。

1. 关键技术介绍

  • Playwright:一个由微软开发的用于 Web 浏览器自动化的库,支持 Chromium、Firefox 和 WebKit 等多种浏览器,可以轻易的实现页面的各种自动化操作,比如模拟点击,模拟键盘输入,甚至可以通过 JavaScript 或 Python(通过 Playwright for Python)来实现爬虫功能。

  • Turndown:一个 HTML 到 Markdown 的转换器,可以帮助我们将从网页上抓取的 HTML 内容,转换为简洁的 Markdown 格式,便于存储和展示。

2. 安装依赖

为了实现网站内容抓取和转换,我们需要先安装 PlaywrightTurndown:

bash 复制代码
# 安装 Playwright
pnpm add playwright
pnpm exec install playwright

# 安装 Turndown
pnpm add turndown

3. 爬虫代码实现

以下是基于 PlaywrightTurndown 的网站内容抓取和转换代码:

typescript 复制代码
import { Injectable } from '@nestjs/common';
import { chromium } from 'playwright';
import TurndownService from 'turndown';

@Injectable()
export class CrawlerService {
  private turndown: TurndownService;

  constructor() {
    // 初始化 Turndown 转换器
    this.turndown = new TurndownService({
      bullet: '-', // 无序列表符号
      codeBlock: '```', // 代码块符号
      headingStyle: 'atx', // 标题样式
    });
  }

  async crawl(baseUrl: string): Promise<{ title: string; url: string; content: string }[]> {
    const docs: { title: string; url: string; content: string }[] = [];
    const urls = new Set<string>();
    urls.add(`${baseUrl}/`);

    try {
      await this.recursiveCrawl(baseUrl, docs, urls);
    } catch (err) {
      console.error('爬取失败:', err);
    }

    return docs;
  }

  private async recursiveCrawl(
    url: string,
    docs: { title: string; url: string; content: string }[],
    urls: Set<string>,
  ): Promise<void> {
    const browser = await chromium.launch();
    const context = await browser.newContext();
    const page = await context.newPage();

    try {
      await page.goto(url, { waitUntil: 'networkidle' });
      const title = await page.title();

      // 移除所有干扰元素
      await page.evaluate(() => {
        document.querySelectorAll('script, style, link[rel="stylesheet"], [style]').forEach(el => el.remove());
      });

      // 获取页面内容并转换为 Markdown
      const content = await page.content();
      const md = await new Promise(r => {
         r(this.turndown.turndown(content));
      });

      docs.push({ title, url, content: md });

      // 提取所有链接并递归抓取
      const links = await page.$$eval('a[href]', (elements) =>
        elements.map((el) => el.href?.replace(/#.*$/, '')).filter((link) => link.startsWith(baseUrl))
      );
      
      console.log(`正在抓取:${title} - ${url}`);

      for (const link of links) {
        if (!urls.has(link)) {
          urls.add(link);
          await page.waitForTimeout(50);
          await this.recursiveCrawl(link, docs, urls);
        }
      }
    } catch (err) {
      console.error(`抓取失败: ${url}`, err);
    } finally {
      await page.close();
      await context.close();
      await browser.close();
    }
  }
}

4. 代码说明

  1. 无头浏览器启动

    使用 chromium.launch() 启动无头浏览器,这是一种在后台运行的浏览器,可以模拟用户的行为,如浏览网站、点击链接等。

  2. 页面内容抓取与清理

    • 使用 page.goto() 访问目标网页,并等待页面加载完成。
    • 使用 page.evaluate() 执行 JavaScript 代码,移除网页中的 <script><style>[style] 等干扰元素,以便更准确地提取内容。
  3. HTML 转 Markdown

    使用 Turndown 将网页的 HTML 内容转换为 Markdown 格式。Turndown 支持自定义配置,可以根据需求调整 Markdown 的输出格式。

  4. 递归抓取链接

    通过 page.$$eval() 提取页面中的所有链接,并递归地对每个链接进行抓取,确保能够抓取到整个网站的内容。

5. 知识库数据存储

我们可以将抓取的 Markdown 数据转换为向量,并存储到 Milvus 中,从而构建一个基于向量的知识库。

6. 应用场景

  • 自动化知识库文档构建

    • 从多个网站抓取相关知识内容,并统一存储到知识库中,方便后续RAG系统使用。
  • 内容更新监测

    • 定期抓取网站内容,监测内容的变化,并及时更新知识库数据。

7. 注意事项

  • 遵守法律法规

    • 在爬取网站内容时,必须遵守相关法律法规,尊重网站的版权和隐私政策。
  • 避免过度请求

    • 合理设置爬虫的请求频率和并发数,避免对目标网站造成过大压力,导致服务器崩溃或被封禁。
  • 处理反爬机制

    • 部分网站可能会采取反爬措施,如验证码、IP 封禁等。可以通过设置合理的请求头、使用代理 IP 或模拟用户行为等方式,降低被检测的风险。

8. 示例运行

为了验证爬虫功能是否正常,可以运行以下代码:

typescript 复制代码
async function bootstrap() {
  const baseUrl = 'https://docs.nestjs.com';
  const crawler = new CrawlerService();
  const docs = await crawler.crawl(baseUrl);

  console.log('抓取完成,共抓取了', docs.length, '个页面');
  // 打印结果到控制台或保存到文件
}

bootstrap();

总结

通过 NestJS、Playwright 和 Turndown 的结合,我们可以轻松实现对网站内容的抓取和转换,并将其存储到知识库中。这种技术不仅可以用于知识文档的自动化抓取,还可以用于构建智能体的内容监测系统。

相关推荐
咨询187150651271 分钟前
高企复审奖补!2025年合肥市高新技术企业重新认定奖励补贴政策及申报条件
大数据·人工智能·区块链
亚洲小炫风8 分钟前
flutter 中各种日志
前端·flutter·日志·log
Guheyunyi13 分钟前
智能照明系统:照亮智慧生活的多重价值
大数据·前端·人工智能·物联网·信息可视化·生活
徐同保28 分钟前
通过AzureOpenAI请求gpt-4.1-mini
前端
云天徽上31 分钟前
【数据可视化-27】全球网络安全威胁数据可视化分析(2015-2024)
人工智能·安全·web安全·机器学习·信息可视化·数据分析
ONEYAC唯样38 分钟前
“在中国,为中国” 英飞凌汽车业务正式发布中国本土化战略
大数据·人工智能
红尘散仙39 分钟前
四、WebGPU 基础入门——Uniform 缓冲区与内存对齐
前端·rust·gpu
mozun202043 分钟前
产业观察:哈工大机器人公司2025.4.22
大数据·人工智能·机器人·创业创新·哈尔滨·名校
-一杯为品-1 小时前
【深度学习】#9 现代循环神经网络
人工智能·rnn·深度学习
硅谷秋水1 小时前
ORION:通过视觉-语言指令动作生成的一个整体端到端自动驾驶框架
人工智能·深度学习·机器学习·计算机视觉·语言模型·自动驾驶