.NET使用分布式网络爬虫框架DotnetSpider快速开发爬虫功能
前言
前段时间有同学在微信群里提问,要使用.NET开发一个简单的爬虫功能但是没有做过无从下手。今天给大家推荐一个轻量、灵活、高性能、跨平台的分布式网络爬虫框架(可以帮助 .NET 工程师快速的完成爬虫的开发):DotnetSpider。
注意:为了自身安全请在国家法律允许范围内开发网络爬虫功能。
框架设计图
整个爬虫设计是纯异步的,利用消息队列进行各个组件的解耦,若是只需要单机爬虫则不需要做任何额外的配置,默认使用了一个内存型的消息队列;若是想要实现一个纯分布式爬虫,则需要引入一个消息队列即可,后面会详细介绍如何实现一个分布式爬虫。

框架源码

开发爬虫需求
爬取博客园10天推荐排行第一页的文章标题、文章简介和文章地址,并将其保存到对应的txt文本中。

快速开始
创建SpiderSample控制台



安装DotnetSpider Nuget包
搜索:DotnetSpider

添加Serilog日志组件
搜索:Serilog.AspNetCore

RecommendedRankingModel
    public class RecommendedRankingModel
    {
        /// <summary>
        /// 文章标题
        /// </summary>
        public string ArticleTitle { get; set; }
        /// <summary>
        /// 文章简介
        /// </summary>
        public string ArticleSummary { get; set; }
        /// <summary>
        /// 文章地址
        /// </summary>
        public string ArticleUrl { get; set; }
    }
RecommendedRankingSpider
    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;
            }
        }
    }
Program调用
   internal class Program
   {
       static async Task Main(string[] args)
       {
           Console.WriteLine("Hello, World!");
           await RecommendedRankingSpider.RunAsync();
           Console.WriteLine("数据抓取完成");
       }
   }抓取数据和页面数据对比
抓取数据:

页面数据:

项目源码地址
更多项目实用功能和特性欢迎前往项目开源地址查看,别忘了给项目一个Star支持。
GitHub源码地址:https://github.com/dotnetcore/DotnetSpider
GitHub wiki:https://github.com/dotnetcore/DotnetSpider/wiki
优秀项目和框架精选
该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没)。
https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.md
DotNetGuide技术社区交流群
- DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目推荐、招聘资讯和解决问题的平台。
- 在这个社区中,开发者们可以分享自己的技术文章、项目经验、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
- 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台,为广大.NET开发者带来更多的价值和成长机会。
.NET使用分布式网络爬虫框架DotnetSpider快速开发爬虫功能的更多相关文章
- 爬虫框架: DotnetSpider
		[开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计 一 ,为什么要造轮子 有兴趣的同学可以去各大招聘网站看一下爬虫工程师的要求,大多是JAVA,PYTH ... 
- [开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计
		[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 为什么要造轮子 同学们可以去各大招聘网站查看一下爬虫工程师的要求,大多是招JA ... 
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计
		[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 为什么要造轮子 同学们可以去各大招聘网站查看一下爬虫工程师 ... 
- java SSM框架 代码生成器 快速开发平台 websocket即时通讯 shiro redis
		A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 , ... 
- JAVA爬虫实践(实践三:爬虫框架webMagic和csdnBlog爬虫)
		WebMagic WebMagic是一个简单灵活的Java爬虫框架.基于WebMagic,你可以快速开发出一个高效.易维护的爬虫. 采用HttpClient可以实现定向的爬虫,也可以自己编写算法逻辑来 ... 
- 十个Python爬虫武器库示例,十个爬虫框架,十种实现爬虫的方法!
		一般比价小型的爬虫需求,我是直接使用requests库 + bs4就解决了,再麻烦点就使用selenium解决js的异步 加载问题.相对比较大型的需求才使用框架,主要是便于管理以及扩展等. 1.Scr ... 
- C# 爬虫框架实现 流程_爬虫结构/原理
		目录链接:C# 爬虫框架实现 概述 首先需要讲的是,爬虫的原理.其实在我看来,爬虫只是用来解决以下四个问题的工具: 提取哪些网页 提取网页上的哪些内容 存储到哪里(推荐数据库/开源类/Console) ... 
- 干货!JNPF快速开发平台功能一览
		JNPF,采用主流的两大技术Java/.Net开发,是一套低代码开发平台,可视化开发环境,有拖拽式的代码生成器,灵活的权限配置.SaaS服务,强大的接口对接,随心可变的工作流引擎,一站式开发多端使 ... 
- JavaWeb_(Hibernate框架)使用Hibernate开发用户注册功能
		使用Hibernate开发用户注册功能: 用户在register.jsp表单成功后,页面跳转到login.html,数据库中会存放用户注册的信息 <%@ page language=" ... 
- [开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [二] 基本使用
		[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 使用环境 Visual Studio 2015 or later .NET 4 ... 
随机推荐
- 【技术积累】Java里的volatile关键字到底能干嘛?
			7.4 最害怕的一集 - volatile 7.4.1 最简单的一集 - volatile 语义 (难度 : ) 读 -> 读一个 volatile 必须从 主内存读 写 -> 写一个 v ... 
- 一个超经典 WinForm 卡死问题的最后一次反思
			一:背景 1. 讲故事 在我分析的 200+ dump 中,同样会遵循着 28原则,总有那些经典问题总是反复的出现,有很多的朋友就是看了这篇 一个超经典 WinForm 卡死问题的再反思 找到我,说 ... 
- python 运行环境变为 pytest in (for) xxx.py原因
			因为本人的自定义函数名称开头为test,在.py文件内我用了unittest框架,所以环境随着变化了. 修改回去很简单,只要不使用test开头或者换个文件夹. 
- 使用Java Xpath 爬取某易云歌曲
			本文使用Java xpath 爬取某易云歌曲,并下载至本地. 代码仅用于个人学习使用,欢迎各位大佬提出建议. 1.添加依赖 <dependency> <groupId>cn.w ... 
- redis分布式锁,setnx+lua脚本的java实现
			1 前言 在现在工作中,为保障服务的高可用,应对单点故障.负载量过大等单机部署带来的问题,生产环境常用多机部署.为解决多机房部署导致的数据不一致问题,我们常会选择用分布式锁. 目前其他比较常见的实现方 ... 
- 《SQL与数据库基础》02. SQL-DDL
			目录 DDL 库管理 表管理 本文以 MySQL 为例 DDL 库管理 查看有哪些数据库: SHOW DATABASES; 使用某个数据库: USE 数据库名; 查看当前使用的数据库: SELECT ... 
- uwsgi配置
			编辑nginx配置: server { listen 8098; server_name 127.0.0.1; location / { include uwsgi_params; # uwsgi_p ... 
- Springboot优雅参数校验,统一响应,异常处理
			1.统一响应 (1)统一状态码 首先定义一个状态码接口,所有状态码都需要实现它 public interface StatusCode { public int getCode(); public S ... 
- Redis系列24:Redis使用规范
			Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ... 
- 报错AttributeError: Attempted to set WANDB to False, but CfgNode is immutable
			问题 今天在跑代码的时候,使用到了wandb记录训练数据. 我在23服务器上跑的好好的,但将环境迁移到80服务器上重新开始跑时,却遇到了如下报错 看这个报错信息是由于wandb没有apis这个属 ... 
