2018-07-09 23:42:03 +08:00
2018-06-04 15:48:33 +08:00
2018-07-04 23:31:44 +08:00
2018-04-05 00:10:30 +08:00

NScrapy

buildpass license netversion release

简介 / Introduction

NScrapy 是基于 .NET Core 异步编程框架和 Redis 内存存储的开源分布式爬虫框架。NScrapy 的整体思想源于知名的 Python 爬虫框架 Scrapy,整体写法也接近于 Scrapy,支持分布式部署、丰富的中间件扩展以及流式(Fluent)API。

NScrapy is a distributed spider framework based on .NET Core async programming and Redis. Inspired by the famous Python framework Scrapy, NScrapy offers a similar development experience with support for distributed deployment, middleware extensions, and a Fluent API.


快速开始 / Quick Start

安装 / Installation

dotnet add package NScrapy.Infra
dotnet add package NScrapy.Scheduler

编写你的第一个爬虫 / Write Your First Spider

// Local spider
NScrapy.CreateSpider("MySpider")
    .StartUrl("https://example.com")
    .OnResponse(r => {
        Console.WriteLine(r.CssSelector("title::text").Extract());
    })
    .AddPipeline<MyPipeline>()
    .Configure(o => o.Concurrency = 5)
    .Run();

启动 NScrapy Shell: Start the NScrapy Shell:

var shell = NScrapy.Shell.NScrapy.GetInstance();
shell.Crawl("JobSpider");

Docker 部署 / Docker Deployment

简介 / Overview

NScrapy 支持通过 Docker Compose 进行容器化部署,提供三种模式:

NScrapy supports containerized deployment via Docker Compose with three modes:

模式 / Mode 适用场景 / Use Case Redis
local-only 单节点,无需 Redis / Single-node, no Redis 无 / None (InMemoryScheduler)
local-redis 同主机多工作节点 / Multi-worker on same host 本地 Redis 容器 / Local Redis container
managed-redis 云端/生产部署 / Cloud / production deploy 外部 Redis / External Redis

前置条件 / Prerequisites

  • Docker & Docker Compose v2+
  • .NET 10.0(用于本地开发构建 / for local development/builds)

快速启动 / Quick Start

1. 克隆项目 / Clone the project

git clone https://github.com/your-org/NScrapy.git
cd NScrapy

2. 创建 .env 配置文件 / Create a .env config file

# 托管 Redis 模式示例(如 Azure Redis Cache)
# Example for managed-redis mode (Azure Redis Cache)
cat > .env << 'EOF'
REDIS_ENABLED=true
REDIS_HOST=your-redis.redis.cache.windows.net
REDIS_PORT=6380
REDIS_PASSWORD=your-access-key-here
REDIS_USESSL=true
EOF

3. 选择模式并启动 / Choose your mode and start

# 模式 1:本地仅限(无 Redis)
# Mode 1: Local only (no Redis)
docker-compose up -d

# 模式 2:本地 + 本地 Redis 容器
# Mode 2: Local + local Redis container
docker-compose --profile local-redis up -d

# 模式 3:托管 Redis(需先取消 .env 中 Redis 主机注释)
# Mode 3: Managed Redis (uncomment Redis host in .env first)
docker-compose up -d

4. 扩缩容 Spider 和 Downloader / Scale Spider and Downloader workers

# 运行 3 个 Spider 实例和 4 个 Downloader 工作进程
# Run 3 spider instances and 4 downloader workers
docker-compose up -d --scale spider=3 --scale downloader=4

配置说明 / Configuration

所有设置通过环境变量控制。JSON 配置文件(appsettings.spider.json、appsettings.downloader.json)作为默认值,运行时会由环境变量覆盖。

All settings are controlled via environment variables. The JSON config files serve as defaults; environment variables override them at runtime.

变量 / Variable 说明 / Description 默认值 / Default
REDIS_ENABLED 启用 Redis 调度器 / Enable Redis scheduler false
REDIS_HOST Redis 主机名 / Redis hostname redis
REDIS_PORT Redis 端口 / Redis port 6379
REDIS_PASSWORD Redis 密码 / Redis password (empty)
REDIS_USESSL 使用 TLS/SSL false
SCHEDULER_TYPE 调度器类名 / Scheduler class name InMemoryScheduler

项目结构 / Project Structure

NScrapy/
├── docker-compose.yml          # 三合一 compose 文件 / All-in-one compose for 3 modes
├── Dockerfile.Spider           # Spider 多阶段构建 / Multi-stage build for Spider
├── Dockerfile.Downloader       # Downloader 多阶段构建 / Multi-stage build for Downloader
├── appsettings.spider.json     # Spider 默认配置 / Default Spider config
├── appsettings.downloader.json # Downloader 默认配置 / Default Downloader config
├── NScrapy/                    # NScrapy.Shell 库
├── NScrapy.Project/            # Spider 入口 / Spider entry point (Main)
├── NScrapy.DownloaderShell/    # Downloader 工作进程 / Downloader worker
└── ...

手动构建镜像 / Building Images Manually

# 构建 Spider 镜像
# Build Spider image
docker build -f Dockerfile.Spider -t nscrapy-spider .

# 构建 Downloader 镜像
# Build Downloader image
docker build -f Dockerfile.Downloader -t nscrapy-downloader .

架构 / Architecture

                    ┌─────────────────┐
                    │  Spider(s)      │  ← 调度请求 / Schedules requests
                    │  (Crawler logic) │
                    └────────┬────────┘
                             │ Redis queues
                    ┌─────────▼────────┐
                    │  Downloader(s)  │  ← HTTP 工作器 / HTTP workers
                    │  (Workers)       │
                    └─────────────────┘

编程指南 / Programming Guide

NScrapy 提供流式 API,让爬虫编写更加简洁直观。通过 NScrapy.CreateSpider() 可以链式调用配置爬虫行为,支持本地运行和分布式运行两种模式。

NScrapy provides a Fluent API for writing spiders in a concise and intuitive chain-call style. Use NScrapy.CreateSpider() to configure and run spiders, supporting both local and distributed modes.

本地爬虫 / Local Spider

// Local spider / 本地爬虫
NScrapy.CreateSpider("MySpider")
    .StartUrl("https://example.com")
    .OnResponse(r => {
        Console.WriteLine(r.CssSelector("title::text").Extract());
    })
    .AddPipeline<MyPipeline>()
    .Configure(o => o.Concurrency = 5)
    .Run();

分布式爬虫 / Distributed Spider

// Distributed spider / 分布式爬虫
NScrapy.CreateSpider("MySpider")
    .StartUrl("https://example.com")
    .OnResponse(r => { /* parse / 解析 */ })
    .Distributed(d => d
        .UseRedis("localhost:6379")
        .ReceiverQueue("nscrapy:requests")
        .ResponseQueue("nscrapy:responses")
    )
    .Run();

SpiderOptions 配置项 / Configuration Options

选项 / Option 类型 / Type 说明 / Description
Concurrency int 并发请求数(默认 1)/ Concurrent requests, default 1
DelayMs int 请求间隔毫秒(默认 0)/ Delay between requests (ms), default 0
MaxRetries int 最大重试次数(默认 3)/ Max retry count, default 3
TimeoutMs int 请求超时毫秒(默认 30000)/ Request timeout (ms), default 30000
UserAgents List<string> User-Agent 列表,随机选用 / User-Agent list, randomly selected
NScrapy.CreateSpider("MySpider")
    .StartUrl("https://example.com")
    .OnResponse(r => { /* parse / 解析 */ })
    .Configure(o => {
        o.Concurrency = 5;
        o.DelayMs = 1000;
        o.MaxRetries = 3;
        o.TimeoutMs = 15000;
        o.UserAgents = new List<string> {
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
        };
    })
    .Run();

JsRenderMiddleware(JS 渲染中间件)

启用 JavaScript 渲染支持(用于抓取 SPA 页面的内容):

Enable JavaScript rendering support (for crawling SPA pages):

NScrapy.CreateSpider("MySpider")
    .StartUrl("https://example.com")
    .OnResponse(r => { /* parse / 解析 */ })
    .AddDownloaderMiddleware<JsRenderMiddleware>()
    .Run();

⚠️ 注意:JsRenderMiddleware 目前为存根实现,功能开发中。 ⚠️ Note: JsRenderMiddleware is currently a stub implementation; full functionality is under development.


分布式配置 / Distributed Configuration

Redis 配置 / Redis Configuration

Spider 端 / Spider Side

修改项目中的 appsettings.json:

Modify appsettings.json in your project:

{
  "Scheduler": {
    "SchedulerType": "NScrapy.Scheduler.RedisExt.RedisScheduler"
  },
  "Scheduler.RedisExt": {
    "RedisServer": "192.168.0.106",
    "RedisPort": "6379",
    "ReceiverQueue": "NScrapy.Downloader",
    "ResponseQueue": "NScrapy.ResponseQueue"
  }
}

Downloader 端 / Downloader Side

修改 NScrapy.DownloaderShell.dll 同层目录中的 appsettings.json:

Modify appsettings.json under NScrapy.DownloaderShell.dll directory:

{
  "Scheduler": {
    "SchedulerType": "NScrapy.Scheduler.RedisExt.RedisScheduler"
  },
  "Scheduler.RedisExt": {
    "RedisServer": "192.168.0.106",
    "RedisPort": "6379",
    "ReceiverQueue": "NScrapy.Downloader",
    "ResponseQueue": "NScrapy.ResponseQueue"
  }
}

单独运行 DownloaderShell: Run DownloaderShell individually:

dotnet /path/to/NScrapy.DownloaderShell.dll

状态更新中间件 / Status Updater Middleware

如果需要将 Downloader 状态更新到 Redis(用于监控),可以在 appsettings.json 中添加:

If you want to update Downloader status to Redis (for monitoring), add to appsettings.json:

"DownloaderMiddlewares": [
  { "Middleware": "NScrapy.DownloaderShell.StatusUpdaterMiddleware" }
]

💡 NScrapyWebConsole 会从 Redis 中读取 Downloader 状态数据。 💡 NScrapyWebConsole reads Downloader status from Redis.

MongoDB Pipeline

将爬取的数据存储到 MongoDB:

Save crawled data to MongoDB:

public class MongoItemPipeline : IPipeline<JobItem>
{
    private MongoClient client = new MongoClient("mongodb://localhost:27017");
    public async void ProcessItem(JobItem item, ISpider spider)
    {
        var db = client.GetDatabase("NScrapy");
        var collection = db.GetCollection<JobItem>("JobItem");
        await collection.InsertOneAsync(item);
    }
}

添加到 appsettings.json: Add to appsettings.json:

"Pipelines": [
  { "Pipeline": "NScrapy.Project.MongoItemPipeline" }
]

CSV Pipeline

将数据保存为 CSV 文件:

Save data to CSV file:

public class CSVItemPipeline : IPipeline<JobItem>
{
    private string startTime = DateTime.Now.ToString("yyyyMMddhhmm");

    public void ProcessItem(JobItem item, ISpider spider)
    {
        var info = $"{item.Title},{item.Firm},{item.Salary},{item.Time},{System.Environment.NewLine}";
        Console.WriteLine(info);
        File.AppendAllText($"output-{startTime}.csv", info, Encoding.UTF8);
    }
}

添加到 appsettings.json: Add to appsettings.json:

"Pipelines": [
  { "Pipeline": "NScrapy.Project.MongoItemPipeline" },
  { "Pipeline": "NScrapy.Project.CSVItemPipeline" }
]

旧版 API / Legacy API

📄 旧版类继承 API 文档已移至 LEGACY.md。 For legacy class-inheritance API documentation, see LEGACY.md.

S
Description
NScrapy is a .net core corss platform Distributed Spider Framework which provide an easy way to write your own Spider
Readme Apache-2.0 634 KiB
Languages
C# 100%