一小时掌握:使用ScrapySharp和C#打造新闻下载器

亿牛云

引言

爬虫技术是指通过编程的方式,自动从互联网上获取和处理数据的技术。爬虫技术有很多应用场景,比如搜索引擎、数据分析、舆情监测、电商比价等。爬虫技术也是一门有趣的技术,可以让你发现网络上的各种有价值的信息。

本文将介绍如何使用ScrapySharp和C#语言,打造一个简单的新闻下载器,可以从指定的新闻网站上抓取新闻标题、摘要、正文、作者、发布时间等信息,并保存到本地文件中。本文的目的是让你在一小时内掌握ScrapySharp和C#的基本用法,以及爬虫技术的基本原理和技巧。

ScrapySharp和C#的介绍

ScrapySharp是一个基于.NET的爬虫框架,它提供了一系列的类和方法,可以方便地实现爬虫的功能,比如发送请求、解析响应、提取数据、保存数据等。ScrapySharp的核心类是ScrapingBrowser,它模拟了一个浏览器的行为,可以执行JavaScript、处理Cookie、设置代理等。ScrapySharp还支持CSS选择器和XPath语法,可以灵活地定位网页中的元素。

C#是一种面向对象的编程语言,它是.NET平台的主要语言,可以运行在Windows、Linux、Mac等操作系统上。C#语言简洁、强大、高效,拥有丰富的类库和工具,可以开发各种类型的应用程序,包括桌面应用、网站、移动应用、游戏等。C#还支持多线程编程,可以充分利用CPU的资源,提高程序的性能。

新闻下载器的设计

本文的新闻下载器的设计思路如下:

  • 首先,定义一个News类,用来存储新闻的各种属性,比如标题、摘要、正文、作者、发布时间等。
  • 然后,定义一个NewsDownloader类,用来实现新闻下载器的主要逻辑,包括以下几个方法:
    • 构造方法,用来初始化ScrapingBrowser对象,设置代理、超时、用户代理等参数。
    • GetNewsUrls方法,用来从指定的新闻网站的首页上,获取所有新闻的链接,并返回一个字符串列表。
    • GetNewsContent方法,用来从指定的新闻链接上,获取新闻的内容,并返回一个News对象。
    • SaveNews方法,用来将一个News对象保存到本地文件中,文件名为新闻的标题,文件格式为txt。
    • DownloadNews方法,用来下载所有新闻,并保存到本地文件夹中,文件夹名为新闻网站的域名。
  • 最后,定义一个Program类,用来作为程序的入口,创建一个NewsDownloader对象,并调用其DownloadNews方法,传入要爬取的新闻网站的地址。

新闻下载器的代码

本文的新闻下载器的代码如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using HtmlAgilityPack;
using ScrapySharp.Extensions;
using ScrapySharp.Network;

namespace NewsDownloader
{
    // 定义一个News类,用来存储新闻的各种属性
    public class News
    {
        public string Title { get; set; } // 标题
        public string Summary { get; set; } // 摘要
        public string Content { get; set; } // 正文
        public string Author { get; set; } // 作者
        public string Time { get; set; } // 发布时间
    }

    // 定义一个NewsDownloader类,用来实现新闻下载器的主要逻辑
    public class NewsDownloader
    {
        private ScrapingBrowser browser; // 定义一个ScrapingBrowser对象,用来模拟浏览器的行为
        //亿牛云 设置爬虫代理加强版
        private string proxyDomain = "http://www.16yun.cn"; // 定义代理的域名
        private int proxyPort = 9010; // 定义代理的端口
        private string proxyUser = "16YUN"; // 定义代理的用户名
        private string proxyPass = "16IP"; // 定义代理的密码

        // 构造方法,用来初始化ScrapingBrowser对象,设置代理、超时、用户代理等参数
        public NewsDownloader()
        {
            browser = new ScrapingBrowser();
            browser.Timeout = TimeSpan.FromSeconds(10); // 设置超时时间为10秒
            browser.UserAgent = new FakeUserAgent("Chrome", 88.0); // 设置用户代理为Chrome 88.0
            browser.UseDefaultCookiesParser = false; // 禁用默认的Cookie解析器
            browser.Proxy = new WebProxy(proxyDomain, proxyPort); // 设置代理
            browser.Proxy.Credentials = new NetworkCredential(proxyUser, proxyPass); // 设置代理的凭证
        }

        // GetNewsUrls方法,用来从指定的新闻网站的首页上,获取所有新闻的链接,并返回一个字符串列表
        public List<string> GetNewsUrls(string url)
        {
            List<string> newsUrls = new List<string>(); // 定义一个字符串列表,用来存储新闻的链接
            try
            {
                WebPage homePage = browser.NavigateToPage(new Uri(url)); // 使用ScrapingBrowser对象访问新闻网站的首页,并获取WebPage对象
                HtmlNode homeNode = homePage.Html; // 从WebPage对象中获取HtmlNode对象,表示网页的HTML文档
                IEnumerable<HtmlNode> newsNodes = homeNode.CssSelect("a[href*='/news/']"); // 使用CSS选择器,从HtmlNode对象中获取所有包含'/news/'的a标签的HtmlNode对象,表示新闻的链接
                foreach (HtmlNode newsNode in newsNodes) // 遍历所有新闻的链接
                {
                    string newsUrl = newsNode.GetAttributeValue("href", null); // 从HtmlNode对象中获取href属性的值,表示新闻的链接
                    if (newsUrl != null && !newsUrls.Contains(newsUrl)) // 如果新闻的链接不为空,且不在字符串列表中
                    {
                        newsUrls.Add(newsUrl); // 将新闻的链接添加到字符串列表中
                    }
                }
            }
            catch (Exception ex) // 捕获异常
            {
                Console.WriteLine("GetNewsUrls error: " + ex.Message); // 在控制台输出异常信息
            }
            return newsUrls; // 返回字符串列表
        }

        // GetNewsContent方法,用来从指定的新闻链接上,获取新闻的内容,并返回一个News对象
        public News GetNewsContent(string url)
        {
            News news = new News(); // 定义一个News对象,用来存储新闻的内容
            try
            {
                WebPage newsPage = browser.NavigateToPage(new Uri(url)); // 使用ScrapingBrowser对象访问新闻的链接,并获取WebPage对象
                HtmlNode newsNode = newsPage.Html; // 从WebPage对象中获取HtmlNode对象,表示网页的HTML文档
                HtmlNode titleNode = newsNode.CssSelect("h1").FirstOrDefault(); // 使用CSS选择器,从HtmlNode对象中获取第一个h1标签的HtmlNode对象,表示新闻的标题
                HtmlNode summaryNode = newsNode.CssSelect("p.summary").FirstOrDefault(); // 使用CSS选择器,从HtmlNode对象中获取第一个p标签,且class属性为summary的HtmlNode对象,表示新闻的摘要
                HtmlNode contentNode = newsNode.CssSelect("div.article-content").FirstOrDefault(); // 使用CSS选择器,从HtmlNode对象中获取第一个div标签,且class属性为article-content的HtmlNode对象,表示新闻的正文
                HtmlNode authorNode = newsNode.CssSelect("span.author").FirstOrDefault(); // 使用CSS选择器,从HtmlNode对象中获取第一个span标签,且class属性为author的HtmlNode对象,表示新闻的作者
                HtmlNode timeNode = newsNode.CssSelect("span.time").FirstOrDefault(); // 使用CSS选择器,从HtmlNode对象中获取第一个span标签,且class属性为time的HtmlNode对象,表示新闻的发布时间
                if (titleNode != null) // 如果标题节点不为空
                {
                    news.Title = titleNode.InnerText.Trim(); // 从HtmlNode对象中获取文本内容,并去除两端的空白字符,赋值给News对象的Title属性
                }
                if (summaryNode != null) // 如果摘要节点不为空
                {
                    news.Summary = summaryNode.InnerText.Trim(); // 从HtmlNode对象中获取文本内容,并去除两端的空白字符,赋值给News对象的Summary属性
                }
                if (contentNode != null) // 如果正文节点不为空
                {
                    news.Content = contentNode.InnerText.Trim(); // 从HtmlNode对象中获取文本内容,并去除两端的空白字符,赋值给News对象的Content属性
                }
                if (authorNode != null) // 如果作者节点不为空
                {
                    news.Author = authorNode.InnerText.Trim(); // 从HtmlNode对象中获取文本内容,并去除两端的空白字符,赋值给News对象的Author属性
                }
                if (timeNode != null) // 如果时间节点不为空
                {
                    news.Time = timeNode.InnerText.Trim(); // 从HtmlNode对象中获取文本内容,并去除两端的空白字符,赋值给News对象的Time属性
                }
            }
            catch (Exception ex) // 捕获异常
            {
                Console.WriteLine("GetNewsContent error: " + ex.Message); // 在控制台输出异常信息
            }
            return news; // 返回News对象
        }

        // SaveNews方法,用来将一个News对象保存到本地文件中,文件名为新闻的标题,文件格式为txt
        public void SaveNews(News news, string folder)
        {
            try
            {
                string fileName = news.Title + ".txt"; // 定义文件名为新闻的标题加上.txt后缀
                string filePath = Path.Combine(folder, fileName); // 定义文件路径为文件夹和文件名的组合
                using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8)) // 使用StreamWriter对象,以UTF-8编码,覆盖模式,打开或创建文件
                {
                    writer.WriteLine("标题:" + news.Title); // 写入新闻的标题
                    writer.WriteLine("摘要:" + news.Summary); // 写入新闻的摘要
                    writer.WriteLine("正文:" + news.Content); // 写入新闻的正文
                    writer.WriteLine("作者:" + news.Author); // 写入新闻的作者
                    writer.WriteLine("时间:" + news.Time); // 写入新闻的时间
                }
            }
            catch (Exception ex) // 捕获异常
            {
                Console.WriteLine("SaveNews error: " + ex.Message); // 在控制台输出异常信息
            }
        }

        // DownloadNews方法,用来下载所有新闻,并保存到本地文件夹中,文件夹名为新闻网站的域名
        public void DownloadNews(string url)
        {
            try
            {
                Uri uri = new Uri(url); // 定义一个Uri对象,表示新闻网站的地址
                string folder = uri.Host; // 定义文件夹名为Uri对象的Host属性,表示新闻网站的域名
                if (!Directory.Exists(folder)) // 如果文件夹不存在
                {
                    Directory.CreateDirectory(folder); // 创建文件夹
                }
                List<string> newsUrls = GetNewsUrls(url); // 调用GetNewsUrls方法,获取所有新闻的链接
                Parallel.ForEach(newsUrls, newsUrl => // 使用Parallel类的ForEach方法,对所有新闻的链接进行并行处理,提高采集效率
                {
                    News news = GetNewsContent(newsUrl); // 调用GetNewsContent方法,获取新闻的内容
                    SaveNews(news, folder); // 调用SaveNews方法,将新闻保存到本地文件中
                    Console.WriteLine("Downloaded: " + news.Title); // 在控制台输出下载成功的新闻的标题
                });
                Console.WriteLine("Download completed!"); // 在控制台输出下载完成的提示
            }
            catch (Exception ex) // 捕获异常
            {
                Console.WriteLine("DownloadNews error: " + ex.Message); // 在控制台输出异常信息
            }
        }
    }

    // 定义一个Program类,用来作为程序的入口
    class Program
    {
        static void Main(string[] args)
        {
            NewsDownloader downloader = new NewsDownloader(); // 创建一个NewsDownloader对象
            downloader.DownloadNews("https://www.bbc.com/news"); // 调用其DownloadNews方法,传入要爬取的新闻网站的地址
            Console.ReadKey(); // 等待用户按键
        }
    }
}

结论

本文介绍了如何使用ScrapySharp和C#语言,打造一个简单的新闻下载器,可以从指定的新闻网站上抓取新闻标题、摘要、正文、作者、发布时间等信息,并保存到本地文件中。本文的目的是让你在一小时内掌握ScrapySharp和C#的基本用法,以及爬虫技术的基本原理和技巧。

本文的技术文章和代码仅供参考,你可以根据自己的需求和兴趣,修改或扩展它们,实现更多的功能,比如添加异常处理、日志记录、数据清洗、数据分析等。希望本文能对你的学习和开发有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/310390.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024不容错过的好项目好商机,普通人翻身就靠它了,靠谱创业项目推荐

2024什么最容易挣钱&#xff1f;是火遍全网的单身经济&#xff1f;宠物经济&#xff1f;旅游业&#xff1f;大健康经济&#xff1f;都不是&#xff01;他们确实挣钱&#xff0c;但都不是最容易的。 比如单身经济&#xff0c;卖东西你需要去结合需求去选品&#xff0c;开单身餐厅…

jsoncpp学习

1.环境配置 C 操作 &#xff08;读写&#xff09;json 文件及jsoncpp的配置-CSDN博客 一步步跟下来&#xff0c;就可以了!!! 2.遇到的问题&#xff1a; 读取json文件&#xff0c;出现中文乱码&#xff01;&#xff01;&#xff01; 参考&#xff1a;C ifstream open 读取…

产品经理须知 | 电商API接口接入知识小结

应用程序接口API&#xff08;Application Programming Interface&#xff09;&#xff0c;是提供特定业务输出能力、连接不同系统的一种约定。这里包括外部系统与提供服务的系统&#xff08;中后台系统&#xff09;或后台不同系统之间的交互点。包括外部接口、内部接口&#xf…

uni-app的学习【第二节】

四 路由配置及页面跳转 (1)路由配置 uni-app页面路由全部交给框架统一管理,需要在pages.json里配置每个路由页面的路径以及页面样式(类似小程序在app.json中配置页面路由) (2)路由跳转 uni-app有两种页面路由跳转方式:使用navigator组件跳转(标签式导航)、调用API跳…

JavaWeb- Tomcat

一、概念 老规矩&#xff0c;先看维基百科&#xff1a;Apache Tomcat (called "Tomcat" for short) is a free and open-source implementation of the Jakarta Servlet, Jakarta Expression Language, and WebSocket technologies.[2] It provides a "pure Ja…

能赚钱的GPT Store正式上线!如何将自己的 GPT 放到商店中?

等了两个月&#xff0c;OpenAI 的 GPT Store 今日凌晨终于上线&#xff01;上线 GPT Store 的同时&#xff0c;OpenAI 同步了最新的 GPTs 数据&#xff1a;截止到1月11日&#xff0c;用户已创建300万的GPTs&#xff01; GPTs 开发者可以通过 GPTs 来获利。OpenAI 将在今年第一季…

使用递归将list转换成tree

在产品研发时遇到这样一个问题&#xff0c;对于省市区县这类三级联动的数据&#xff0c;前端插件需要一次把数据全部返回&#xff0c;单纯的使用接口查询字节的没办法满足要求。 如果一次把数据全部返回&#xff0c;前端使用起来很麻烦需要一条一条的进行查找。 常规的使用方…

使用visio画图基础(更新中)

1、画基本图形&#xff1a;正方形长方形&#xff0c;直线虚线 1、在形状这里选中后出现基本形状界面&#xff0c;拖动即可 画直线、虚线修改直线的样式改为虚线即可。 2、在矩形中画网格 先画一个矩形&#xff0c;然后选中&#xff0c;按照箭头选择排列形状。设置3*3。 双击可…

ubuntu18.04.6 搭建mqtt服务器emqx 之docker方式

ubuntu18.04.6 搭建mqtt服务器emqx 之docker方式 前提docker环境已经安装好 如未安装&#xff0c;请参考博文https://blog.csdn.net/a554521655/article/details/134251763 文章目录 ubuntu18.04.6 搭建mqtt服务器emqx 之docker方式安装emqx查看是否安装并启动成功登录前端查 安…

凸优化Convex Optimization期末复习重点和考试笔记(二)凸优化+对偶

接博客【凸优化Convex Optimization期末复习重点和考试笔记&#xff08;一&#xff09;凸集凸函数】 第三部分&#xff1a;凸优化 第四部分&#xff1a;对偶 几种典型的凸函数 以上就是凸优化和对偶函数部分&#xff0c;以及几种常见的凸函数。我们就考到这所以后面的没有整理…

进销存+小程序商城:实现批发零售企业的互联网转型与管理升级

在当今互联网高速发展的时代&#xff0c;越来越多的批发零售企业开始开始考虑转型。在这个行业中&#xff0c;企业要想取得更好的发展&#xff0c;就要积极地拥抱互联网。专属的订货商城小程序是企业转型的第一步。通过将进销存与订货商城一体化&#xff0c;企业可以更好地满足…

Java项目:117SpringBoot动漫论坛网站

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 117SpringBoot动漫论坛网站 一、项目介绍 动漫论坛网站是由SpringBootMybatis开发的&#xff0c;旅游网站分为前台和后台&#xff0c;前台为用户浏览&#xff0c;后台进…

大小论文over,坐等毕业。写点ROS上建图与导航的心得,也不知道对错,欢迎讨论~(对,谨慎阅读,不存在误人子弟哈~.~)

大小论文总算是都搞定了&#xff0c;院审过了送外审了&#xff0c;生死有命富贵在天&#xff0c;希望外审专家大佬们高抬贵手o.O~ 我所理解的建图算法的移植&#xff0c;能不能运行起来&#xff0c;大框架上就是把一棵完整的坐标转换关系的TF树给整理“通顺”&#xff0c;TF&am…

springboot3(二、StreamAPI)

文章目录 一、StreamAPI1.介绍2.代码示例 二、基本用法1.创建流2.流并发3.流并发问题 三、流方法1.中间操作2.终止操作 一、StreamAPI StreamAPI这种函数式编程是声明式编程&#xff0c;声明式编程是一种编程范式&#xff0c;它着重于描述问题的"是什么"&#xff0c…

深入理解.NET框架中的CLR(公共语言运行时)

深入理解.NET框架中的CLR&#xff08;公共语言运行时&#xff09; 引言 .NET框架中的CLR&#xff08;公共语言运行时&#xff09;是.NET应用程序运行的核心。本文将继续探索CLR的核心功能&#xff0c;并详细介绍.NET程序启动时是如何自动加载关键的库和服务来提供这些功能的。…

初识QT。

文章目录 前言一、QWidget1、了解内容main文件中的基本内容。.pro项目文件的内容。mywidget.h文件内容。命名规范和快捷键Qt助手 2、button按钮3、对象树4、信号和槽5、自定义信号和槽函数拓展 6、Lambda表达式7、练习 二、QMainWindow1、菜单栏和菜单项2、工具栏3、状态栏4、铆…

适用于安防 音响 车载等产品中中的音频接口选型分析

在人工智能兴起之后&#xff0c;安防市场就成为了其全球最大的市场&#xff0c;也是成功落地的最主要场景之一。对于安防应用而言&#xff0c;智慧摄像头、智慧交通、智慧城市等概念的不断涌现&#xff0c;对于芯片产业催生出海量需求。今天&#xff0c;我将为大家梳理GLOBALCH…

启用Hyper-V的三种方法,总有一种适合你

想在Windows 10计算机上的虚拟机中安装并运行Linux或更早版本的Windows操作系统吗&#xff1f;你将很高兴知道&#xff0c;你不需要第三方虚拟化软件&#xff08;如VirtualBox&#xff09;来在Windows 10上安装和运行Linux和Windows。 Windows 10中的内置Hyper-V工具允许你创建…

Android Studio 实现飞机大战游戏App

&#x1f345;文章末尾有获取完整项目源码方式&#x1f345; 目录 前言 一、运行演示 二、开发环境 三、完成步骤 步骤 1&#xff1a;创建项目 步骤 2&#xff1a;创建包名 步骤 3&#xff1a;实现启动页 步骤 5&#xff1a;实现用户注册 步骤 6&#xff1a;实现用户登…

逃离支原体又陷入流感 | 揭秘呼吸道感染与肠道菌群的隐秘关联

谷禾健康 成人每年大约会患上两到三次普通感冒&#xff0c;儿童每年可能会患上多达八次。而今年尤为显著&#xff0c;各大医院的儿科还是爆满状态&#xff0c;甚至是一号难求。 肺炎支原体感染还没彻底过去&#xff0c;紧接着流感和其他呼吸道病原体感染又跟来了&#xff0c;医…