项目概述

本项目旨在模仿Crawl4AI,开发一个基于.NET8的简单AI爬虫工具,支持JavaScript渲染,封装为Docker镜像,通过API提供服务,并部署在Ubuntu 24上。以下是详细的架构设计和实施指南。

技术栈

组件技术用途
后端框架ASP.NET Core Web API (.NET8)提供RESTful API,处理爬虫请求
浏览器自动化Playwright for .NET控制无头Chrome,渲染JavaScript
HTML解析HtmlAgilityPack 或 AngleSharp解析HTML,使用CSS/XPath提取数据
容器化Docker打包应用,确保部署一致性

架构设计

1. 应用结构

  • ASP.NET Core Web API:核心服务,暴露端点如POST /api/crawl,接受URL和提取参数(如CSS选择器),返回提取的数据。
  • Playwright for .NET:用于启动无头Chrome浏览器,加载网页并渲染动态内容。
  • HtmlAgilityPack/AngleSharp:解析渲染后的HTML,基于用户提供的CSS或XPath选择器提取数据。
  • 数据格式:输出JSON或Markdown格式,适合AI应用(如RAG或LLM数据管道)。

2. API端点示例

端点方法请求体响应
/api/crawlPOST{ "url": "https://example.com", "extraction": { "type": "css", "selector": "h1" } }{ "data": "Example Domain" }

3. 工作流程

  1. 用户通过API发送爬取请求,指定目标URL和提取规则。
  2. Web API调用Playwright,启动无头Chrome,加载网页并等待动态内容渲染。
  3. 使用HtmlAgilityPack或AngleSharp解析页面HTML,应用CSS/XPath提取数据。
  4. 将提取的数据格式化为JSON或Markdown,返回给用户。
  5. 错误处理:处理无效URL、超时或提取失败等情况,返回适当的错误信息。

实施步骤

1. 项目设置

  • 创建一个新的ASP.NET Core Web API项目:

    dotnet new webapi -n WebCrawler
    
  • 添加必要的NuGet包:

    • Microsoft.Playwright
    • HtmlAgilityPackAngleSharp

2. 集成Playwright

  • 初始化Playwright并配置无头Chrome:

    using var playwright = await Playwright.CreateAsync();
    await using var browser = await playwright.Chromium.LaunchAsync(new() { Headless = true });
    var page = await browser.NewPageAsync();
    await page.GotoAsync("https://example.com");
    
  • 确保等待动态内容加载(如使用page.WaitForSelectorAsync)。

3. 数据提取

  • 使用HtmlAgilityPack解析HTML:

    var doc = new HtmlDocument();
    doc.LoadHtml(await page.ContentAsync());
    var nodes = doc.DocumentNode.SelectNodes("//h1");
    
  • 或使用AngleSharp:

    var config = Configuration.Default;
    var context = BrowsingContext.New(config);
    var document = await context.OpenAsync(req => req.Content(await page.ContentAsync()));
    var elements = document.QuerySelectorAll("h1");
    

4. API控制器

  • 创建控制器处理爬取请求:

    [ApiController]
    [Route("api/[controller]")]
    public class CrawlController : ControllerBase
    {
        [HttpPost]
        public async Task<IActionResult> Crawl([FromBody] CrawlRequest request)
        {
            // Playwright爬取和提取逻辑
            return Ok(new { Data = "提取的数据" });
        }
    }
    

5. Docker打包

  • 创建以下Dockerfile,使用多阶段构建:

    # 构建阶段
    FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
    WORKDIR /src
    COPY ["WebCrawler.csproj", "."]
    RUN dotnet restore
    COPY . .
    RUN dotnet publish -c Release -o /app
    
    # 运行时阶段
    FROM mcr.microsoft.com/playwright/dotnet:v1.51.1-jammy
    WORKDIR /app
    COPY --from=build /app .
    ENTRYPOINT ["dotnet", "WebCrawler.dll"]
    
  • 构建和运行:

    docker build -t webcrawler .
    docker run -p 8080:80 webcrawler
    

6. 部署到Ubuntu 24

  • 安装Docker:

    sudo apt update
    sudo apt install docker.io
    sudo systemctl start docker
    sudo systemctl enable docker
    
  • 运行容器:

    docker run -d -p 8080:80 webcrawler
    
  • 访问API:http://localhost:8080/api/crawl

优化Docker镜像大小

  • 多阶段构建:仅将发布后的应用文件复制到运行时镜像,减少构建工件。
  • 官方镜像microsoft/playwright-dotnet包含预装的浏览器和.NET运行时,避免手动安装。
  • 清理缓存:在构建过程中使用--no-cache或清理临时文件。
  • 局限性:浏览器二进制文件(如Chrome)不可避免地增加镜像大小,可能达到数百MB,但这是支持JavaScript渲染的必要代价。

注意事项

  • Playwright依赖:确保Docker镜像包含所有浏览器运行所需的系统依赖(如字体和库),microsoft/playwright-dotnet已预配置这些依赖。
  • 错误处理:实现健壮的错误处理机制,处理网络错误、超时或无效选择器。
  • 扩展性:当前设计为单URL爬取,如需支持多URL或深度爬取,可添加队列机制或链接跟随逻辑。
  • AI友好性:输出的JSON或Markdown格式适合AI数据管道,可根据需要扩展支持LLM提取(需额外集成AI服务)。

示例API请求

POST /api/crawl
Content-Type: application/json

{
  "url": "https://example.com",
  "extraction": {
    "type": "css",
    "selector": "h1"
  }
}

响应:

{
  "data": "Example Domain"
}