前段時間有同學在微信群裡提問,要使用.NET開發一個簡單的爬蟲功能但是沒有做過無從下手。今天給大家推薦一個輕量、靈活、高效能、跨平臺的分散式網路爬蟲框架(可以幫助 .NET 工程師快速的完成爬蟲的開發):DotnetSpider。
注意:為了自身安全請在國家法律允許範圍內開發網路爬蟲功能。
整個爬蟲設計是純非同步的,利用訊息佇列進行各個元件的解耦,若是隻需要單機爬蟲則不需要做任何額外的設定,預設使用了一個記憶體型的訊息佇列;若是想要實現一個純分散式爬蟲,則需要引入一個訊息佇列即可,後面會詳細介紹如何實現一個分散式爬蟲。
爬取部落格園10天推薦排行第一頁的文章標題、文章簡介和文章地址,並將其儲存到對應的txt文字中。
搜尋:DotnetSpider
搜尋:Serilog.AspNetCore
public class RecommendedRankingModel
{
/// <summary>
/// 文章標題
/// </summary>
public string ArticleTitle { get; set; }
/// <summary>
/// 文章簡介
/// </summary>
public string ArticleSummary { get; set; }
/// <summary>
/// 文章地址
/// </summary>
public string ArticleUrl { get; set; }
}
public class RecommendedRankingSpider : Spider
{
public RecommendedRankingSpider(IOptions<SpiderOptions> options,
DependenceServices services,
ILogger<Spider> logger) : base(options, services, logger)
{
}
public static async Task RunAsync()
{
var builder = Builder.CreateDefaultBuilder<RecommendedRankingSpider>();
builder.UseSerilog();
builder.UseDownloader<HttpClientDownloader>();
builder.UseQueueDistinctBfsScheduler<HashSetDuplicateRemover>();
await builder.Build().RunAsync();
}
protected override async Task InitializeAsync(CancellationToken stoppingToken = default)
{
// 新增自定義解析
AddDataFlow(new Parser());
// 使用控制檯記憶體
AddDataFlow(new ConsoleStorage());
// 新增採集請求
await AddRequestsAsync(new Request("https://www.cnblogs.com/aggsite/topdiggs")
{
// 請求超時10秒
Timeout = 10000
});
}
class Parser : DataParser
{
public override Task InitializeAsync()
{
return Task.CompletedTask;
}
protected override Task ParseAsync(DataFlowContext context)
{
var recommendedRankingList = new List<RecommendedRankingModel>();
// 網頁資料解析
var recommendedList = context.Selectable.SelectList(Selectors.XPath(".//article[@class='post-item']"));
foreach (var news in recommendedList)
{
var articleTitle = news.Select(Selectors.XPath(".//a[@class='post-item-title']"))?.Value;
var articleSummary = news.Select(Selectors.XPath(".//p[@class='post-item-summary']"))?.Value?.Replace("\n", "").Replace(" ", "");
var articleUrl = news.Select(Selectors.XPath(".//a[@class='post-item-title']/@href"))?.Value;
recommendedRankingList.Add(new RecommendedRankingModel
{
ArticleTitle = articleTitle,
ArticleSummary = articleSummary,
ArticleUrl = articleUrl
});
}
using (StreamWriter sw = new StreamWriter("recommendedRanking.txt"))
{
foreach (RecommendedRankingModel model in recommendedRankingList)
{
string line = $"文章標題:{model.ArticleTitle}\r\n文章簡介:{model.ArticleSummary}\r\n文章地址:{model.ArticleUrl}";
sw.WriteLine(line+ "\r\n ==========================================================================================");
}
}
return Task.CompletedTask;
}
}
}
internal class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Hello, World!");
await RecommendedRankingSpider.RunAsync();
Console.WriteLine("資料抓取完成");
}
}
抓取資料:
頁面資料:
更多專案實用功能和特性歡迎前往專案開源地址檢視