# Aneiang.Pa
**Repository Path**: JsuneCloud/Aneiang.Pa
## Basic Information
- **Project Name**: Aneiang.Pa
- **Description**: 一个基于 .NET 开箱即用的爬虫库,使用复杂度极低,提供更灵活的爬虫。预设了对多个主流平台热榜的爬取支持,包括微博、知乎、B 站、百度、抖音、虎扑、头条、腾讯、掘金、澎湃、凤凰网、豆瓣、CSDN、博客园等。项目完全开源,后续将持续增加更多平台和数据类型的支持。
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: https://pa.aneiang.com
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 18
- **Created**: 2026-05-10
- **Last Updated**: 2026-05-10
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
一个基于 .NET 开箱即用的爬虫库,使用复杂度极低,提供更灵活的爬虫。预设了对多个主流平台热榜的爬取支持,包括微博、知乎、B 站、百度、抖音、虎扑、头条、腾讯、掘金、澎湃、凤凰网、豆瓣、CSDN、博客园等。项目完全开源,后续将持续增加更多平台和数据类型的支持。
中文 | English
---
## ✨ 亮点特性
- ✅ **多平台热榜**:微博 / 知乎 / B 站 / 百度 / 抖音 / 虎扑 / 头条 / 腾讯 / 掘金 / 澎湃 / 凤凰网 / 豆瓣 / CSDN / 博客园 / 彩票数据等
- ✅ **动态模型爬取**:`Aneiang.Pa.Dynamic`
- ✅ **ASP.NET Core Web API**:开箱即用的 RESTful API(支持 **数据缓存** 与 **可选授权**)
- ✅ **缓存支持**:None / Memory / Redis(默认 1 小时,可配置)
- ✅ **代理池**:轮询/随机 + 认证代理,降低封禁风险
> **⚠️ 建议抓取间隔 ≥ 5 分钟**,避免频繁抓取导致 IP 被封禁。
>
> **⚠️ 爬取的数据仅限用于个人学习、研究或公益目的。不得用于商业售卖、攻击他人或任何非法活动,否则需自行承担法律责任。**
- GitHub:
- Gitee(同步):
- 热点新闻在线 Demo:
>- DEMO代码已经开源,支持DOCKER一键部署
>- GitHub:
>- Gitee(同步):
---
## 📚 目录
- [架构调整](#架构调整)
- [安装(NuGet)](#安装nuget)
- [聚合包](#聚合包)
- [单个功能包](#单个功能包)
- [已发布包](#已发布包)
- [快速开始(本地 Demo)](#快速开始本地-demo)
- [在你的项目中使用](#在你的项目中使用)
- [🌐 代理池功能(Proxy Pool)](#-代理池功能proxy-pool)
- [🚀 ASP.NET Core Web API 集成(Aneiang.Pa.AspNetCore)](#-aspnet-core-web-api-集成aneiangpaaspnetcore)
- [快速开始(只调用两个扩展方法)](#快速开始只调用两个扩展方法)
- [缓存配置(Scraper)](#缓存配置scraper)
- [授权配置(Scraper:Authorization)](#授权配置scraperauthorization)
- [API 端点说明](#api-端点说明)
- [✨ 高阶用法 - 动态爬取(Aneiang.Pa.Dynamic)](#-高阶用法---动态爬取aneiangpadynamic)
- [贡献](#贡献)
- [许可证](#许可证)
---
## 架构调整
为了更好地组织和扩展功能,项目架构已进行调整:
- `src/News`: 存放所有新闻热榜相关的爬虫项目。
- `src/Sectors`: 存放特定领域的爬虫项目,如动态爬虫和彩票爬虫。
- `src/Core`: 存放核心接口、模型和公共服务。
---
## 安装(NuGet)
项目提供两种聚合包和按需引用的单个功能包,开发者可根据需求选择。
### 聚合包
1. **全局聚合包** (`Aneiang.Pa`):包含所有已实现的功能。
```bash
dotnet add package Aneiang.Pa
```
2. **热榜聚合包** (`Aneiang.Pa.News`):仅包含所有新闻热榜相关的爬虫。
```bash
dotnet add package Aneiang.Pa.News
```
### 单个功能包
如果只需要特定平台或功能,可以按需引用单个包以减小依赖体积。
```bash
# 示例:仅引用百度热榜爬虫
dotnet add package Aneiang.Pa.BaiDu
```
### 已发布包
| Package | 说明 |
| --- | --- |
| **Aneiang.Pa** | **聚合包,包含全部平台实现** |
| Aneiang.Pa.Core | 核心接口与模型、代理池功能 |
| Aneiang.Pa.AspNetCore | ASP.NET Core Web API 扩展(提供 RESTful API 控制器) |
| Aneiang.Pa.Dynamic | 动态爬虫,可爬取任意网站的数据集合 |
| **--- News (热榜) ---** | **---** |
| Aneiang.Pa.News | 热榜聚合包,包含以下所有新闻平台 |
| Aneiang.Pa.BaiDu | 百度热榜爬虫 |
| Aneiang.Pa.Bilibili | B 站热搜爬虫 |
| Aneiang.Pa.WeiBo | 微博热搜爬虫 |
| Aneiang.Pa.ZhiHu | 知乎热榜爬虫 |
| Aneiang.Pa.DouYin | 抖音热榜爬虫 |
| Aneiang.Pa.HuPu | 虎扑热帖/热榜爬虫 |
| Aneiang.Pa.TouTiao | 今日头条热榜爬虫 |
| Aneiang.Pa.Tencent | 腾讯热榜爬虫 |
| Aneiang.Pa.JueJin | 掘金热榜爬虫 |
| Aneiang.Pa.ThePaper | 澎湃热榜爬虫 |
| Aneiang.Pa.DouBan | 豆瓣热榜爬虫 |
| Aneiang.Pa.IFeng | 凤凰网热榜爬虫 |
| Aneiang.Pa.Csdn | CSDN热榜爬虫 |
| Aneiang.Pa.CnBlog | 博客园热榜爬虫 |
| Aneiang.Pa.Lottery | 彩票数据爬虫 |
---
## 快速开始(本地 Demo)
1) 还原 & 构建
```bash
dotnet restore
dotnet build test/Aneiang.Pa.Demo/Aneiang.Pa.Demo.csproj
```
2) 运行 Demo(默认抓取百度热榜,可修改 `ScraperSource`)
```bash
dotnet run --project test/Aneiang.Pa.Demo
```
运行后,将在控制台看到抓取到的百度热榜数据。
---
## 版本与更新
- 版本号以 `Directory.Build.props` 中的 `Version` 为准(当前为 `2.1.5`)。
- 版本变更记录见 [CHANGELOG.md](CHANGELOG.md)。
---
## 在你的项目中使用
### 1. 注册服务
最简单的方式是使用全局注册方法,一键添加所有爬虫功能。
```csharp
// 注册所有爬虫(推荐)
services.AddPaScraper();
```
如果你只需要特定功能,也可以按需注册:
```csharp
// 仅注册热榜爬虫
services.AddNewsScraper();
// 仅注册彩票爬虫
services.AddLotteryScraper();
// 仅注册动态爬虫
services.AddDynamicScraper();
// 仅注册百度热榜爬虫
services.AddBaiDuScraper();
```
### 2. 使用爬虫
注册服务后,你可以从依赖注入容器中获取相应的服务实例。
**获取热榜数据**
```csharp
// 通过工厂模式获取
var factory = scope.ServiceProvider.GetRequiredService();
var scraper = factory.GetScraper(ScraperSource.BaiDu);
var result = await scraper.GetNewsAsync();
// 或直接注入单个爬虫
var baiduScraper = scope.ServiceProvider.GetRequiredService();
var baiduResult = await baiduScraper.GetNewsAsync();
```
**获取彩票数据**
```csharp
var lotteryScraper = scope.ServiceProvider.GetRequiredService();
var ssqResult = await lotteryScraper.GetLotteryDataAsync(LotteryType.SSQ); // 福利彩票
var dltResult = await lotteryScraper.GetLotteryDataAsync(LotteryType.DLT); // 体育彩票
```
---
## 🌐 代理池功能(Proxy Pool)
**支持配置多个代理服务器,自动轮询或随机选择代理进行请求,有效降低封禁风险。**
### 功能特性
- ✅ 支持多个代理服务器配置
- ✅ 支持两种选择策略:轮询(RoundRobin)和随机(Random)
- ✅ 支持带认证的代理(`http://user:password@host:port`)
- ✅ 可通过配置文件或代码配置
- ✅ 未启用时自动退化为普通 HttpClient
### 使用方式
#### 方式1:通过配置文件(推荐)
在 `appsettings.json` 中配置:
```json
{
"Scraper": {
"ProxyPool": {
"Enabled": true,
"Strategy": "RoundRobin",
"Proxies": [
"http://127.0.0.1:7890",
"http://user:password@proxy.example.com:8080",
"http://192.168.1.100:3128"
]
}
}
}
```
在代码中注册:
```csharp
using Aneiang.Pa.Core.Proxy;
var builder = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
// 注册带代理池支持的默认 HttpClient
services.AddPaDefaultHttpClientWithProxy(
proxyConfiguration: context.Configuration.GetSection("Scraper:ProxyPool"));
// 注册爬虫服务(会自动使用配置的 HttpClient)
services.AddNewsScraper(context.Configuration);
})
.Build();
```
#### 方式2:通过代码配置
```csharp
using Aneiang.Pa.Core.Proxy;
services.AddPaDefaultHttpClientWithProxy(
proxyConfigure: options =>
{
options.Enabled = true;
options.Strategy = ProxySelectionStrategy.RoundRobin; // 或 Random
options.Proxies = new List
{
"http://127.0.0.1:7890",
"http://user:password@proxy.example.com:8080",
"http://192.168.1.100:3128"
};
});
services.AddNewsScraper();
```
---
## 🚀 ASP.NET Core Web API 集成(Aneiang.Pa.AspNetCore)
**提供开箱即用的 Web API 控制器,支持 RESTful API 调用和可选授权功能。**
### 安装
```bash
dotnet add package Aneiang.Pa.AspNetCore
```
### 快速开始(只调用两个扩展方法)
> 设计目标:外部项目尽量“少写代码”。
>
> - `AddPaScraperApi(...)`:注册 API + 缓存
> - `AddPaScraperAuthorization(...)`:按需启用授权(支持配置文件 + 可选代码覆盖)
```csharp
using Aneiang.Pa.AspNetCore.Extensions;
using Aneiang.Pa.Lottery.Extensions;
using Aneiang.Pa.News.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
// 业务服务(热榜/彩票等)
builder.Services.AddNewsScraper(builder.Configuration);
builder.Services.AddLotteryScraper();
// 1) 注册 API + 缓存(读取 Scraper 配置节)
builder.Services.AddPaScraperApi(builder.Configuration);
// 2) 如需授权再启用(读取 Scraper:Authorization 配置节,支持可选代码覆盖)
builder.Services.AddPaScraperAuthorization(builder.Configuration);
var app = builder.Build();
app.MapControllers();
app.Run();
```
### 缓存配置(Scraper)
> 默认:`CacheProvider=None`(不缓存),`CacheDuration=01:00:00`(1小时)。
```json
{
"Scraper": {
"CacheProvider": "Memory",
"CacheDuration": "01:00:00",
"Redis": {
"Configuration": "localhost:6379,password=your_password,defaultDatabase=2",
"InstanceName": "Aneiang.Pa:"
}
}
}
```
**CacheProvider 可选值**:
- `None`:不启用缓存
- `Memory`:进程内内存缓存
- `Redis`:Redis 分布式缓存
**Redis 连接字符串常用参数**(StackExchange.Redis):
- `password=xxx`:Redis 密码(requirepass / ACL)
- `user=xxx`:ACL 用户(Redis 6+)
- `defaultDatabase=2`:指定 DB(注意:Redis Cluster 不支持多 DB)
### 授权配置(Scraper:Authorization)
授权支持三种策略:
- `ApiKey`:请求头或查询参数 API Key
- `Custom`:自定义策略 `CustomAuthorizationFunc`
- `Combined`:ApiKey 或 Custom 任意一种通过即可
#### 方式 1:仅配置文件(推荐)
```json
{
"Scraper": {
"Authorization": {
"Enabled": true,
"Scheme": "ApiKey",
"ApiKeys": ["demo-api-key-12345"],
"ApiKeyHeaderName": "X-API-Key",
"ApiKeyQueryParameterName": "apiKey",
"ExcludedRoutes": [
"/api/scraper/health",
"/api/scraper/news/sources"
],
"UnauthorizedMessage": "未授权访问"
}
}
}
```
代码只需:
```csharp
builder.Services.AddPaScraperAuthorization(builder.Configuration);
```
#### 方式 2:配置文件 + 可选代码覆盖(自定义策略示例)
```csharp
builder.Services.AddPaScraperAuthorization(builder.Configuration, configure: opt =>
{
opt.Enabled = true;
opt.Scheme = Aneiang.Pa.AspNetCore.Options.AuthorizationScheme.Custom;
opt.CustomAuthorizationFunc = httpContext =>
{
var token = httpContext.Request.Headers["X-Demo-Token"].ToString();
return token == "valid-token" ? (true, null) : (false, null);
};
});
```
### API 端点说明
| 端点 | 方法 | 说明 | 示例 |
| --- | --- | --- | --- |
| `/api/scraper/news/{source}` | GET | 获取指定平台的热榜 | `/api/scraper/news/BaiDu` |
| `/api/scraper/news/sources` | GET | 获取所有支持的热榜源 | `/api/scraper/news/sources` |
| `/api/scraper/lottery/welfare/{type}` | GET | 获取福利彩票开奖信息 | `/api/scraper/lottery/welfare/SSQ` |
| `/api/scraper/lottery/sport/{type}` | GET | 获取体育彩票开奖信息 | `/api/scraper/lottery/sport/DLT` |
| `/api/scraper/lottery/types` | GET | 获取所有支持的彩票类型 | `/api/scraper/lottery/types` |
| `/api/scraper/health` | GET | 检查所有爬虫健康状态 | `/api/scraper/health?timeoutMs=5000` |
| `/api/scraper/{source}/health` | GET | 检查指定爬虫健康状态 | `/api/scraper/BaiDu/health?timeoutMs=5000` |
---
## ✨ 高阶用法 - 动态爬取(Aneiang.Pa.Dynamic)
### 引入 NuGet
```bash
dotnet add package Aneiang.Pa.Dynamic
```
### 注册
```csharp
services.AddDynamicScraper();
```
### 使用
```csharp
var scraperFactory = scope.ServiceProvider.GetRequiredService();
var testDataSets = await scraperFactory.DatasetScraper("https://www.cnblogs.com/pick");
```
### 定义模型(CnBlogOriginalResult)
```csharp
[HtmlContainer("div", htmlClass: "post-list", htmlId: "post_list", index: 1)]
[HtmlItem("article", htmlClass: "post-item")]
public class CnBlogOriginalResult
{
[HtmlValue("a", htmlClass: "post-item-title")]
public string Title { get; set; }
[HtmlValue(".", attribute: "data-post-id")]
public string Id { get; set; }
[HtmlValue("a", htmlClass: "post-item-title", attribute: "href")]
public string Url { get; set; }
[HtmlValue(htmlXPath: ".//a[@class=\"post-item-author\"]/span")]
public string AuthorName { get; set; }
[HtmlValue("a", htmlClass: "post-item-author", attribute: "href")]
public string AuthorUrl { get; set; }
[HtmlValue("p", htmlClass: "post-item-summary")]
public string Desc { get; set; }
[HtmlValue(htmlXPath: ".//footer[@class=\"post-item-foot\"]/span[1]")]
public string CreateTime { get; set; }
[HtmlValue(htmlXPath: ".//footer[@class=\"post-item-foot\"]/a[2]")]
public string CommentCount { get; set; }
[HtmlValue(htmlXPath: ".//footer[@class=\"post-item-foot\"]/a[3]")]
public string LikeCount { get; set; }
[HtmlValue(htmlXPath: ".//footer[@class=\"post-item-foot\"]/a[4]")]
public string ReadCount { get; set; }
}
```
### HTML 示例(节选)
```html
```
### 特性说明
- `HtmlContainerAttribute`:数据集容器特性(支持 id/class/xpath)
- `HtmlItemAttribute`:数据项特性(支持 id/class/xpath)
- `HtmlValueAttribute`:字段取值特性(支持 id/class/xpath,可指定 attribute)
**PS:以上三个特性都支持 XPath 检索 HTML 标签,`HTMLXPath` 不为空时,其他属性不生效。**
---
## 贡献
- 欢迎 PR / Issue,尤其是新增平台爬虫、改进解析与健壮性
- 提交前请保持代码风格一致,并附带简要说明和必要的测试
- 如果希望在 NuGet 包中发布你新增的平台,请在 Issue 先讨论方案
## 许可证
Aneiang.Pa 采用 [MIT 许可证](LICENSE)。