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

本文涉及的产品
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: 本文将介绍如何使用ScrapySharp和C#语言,打造一个简单的新闻下载器,可以从指定的新闻网站上抓取新闻标题、摘要、正文、作者、发布时间等信息,并保存到本地文件中。本文的目的是让你在一小时内掌握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#的基本用法,以及爬虫技术的基本原理和技巧。

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

相关文章
|
PyTorch 算法框架/工具
pytorch中torch.clamp()使用方法
pytorch中torch.clamp()使用方法
1559 0
pytorch中torch.clamp()使用方法
|
11月前
|
机器学习/深度学习 数据采集 人工智能
智能嗅探AJAX触发:机器学习在动态渲染中的创新应用
随着Web技术发展,动态加载数据的网站(如今日头条)对传统爬虫提出新挑战:初始HTML无完整数据、请求路径动态生成且易触发反爬策略。本文以爬取“AI”相关新闻为例,探讨了通过浏览器自动化、抓包分析和静态逆向接口等方法采集数据的局限性,并提出借助机器学习智能识别AJAX触发点的解决方案。通过特征提取与模型训练,爬虫可自动推测数据接口路径并高效采集。代码实现展示了如何模拟AJAX请求获取新闻标题、简介、作者和时间,并分类存储。未来,智能化将成为采集技术的发展趋势。
291 1
智能嗅探AJAX触发:机器学习在动态渲染中的创新应用
|
10月前
|
搜索推荐 数据挖掘 计算机视觉
小红书视频图文提取:采集+CV的实战手记
这是一套用于自动抓取小红书热门视频内容的工具脚本,支持通过关键词搜索提取前3名视频的封面图、视频文件及基本信息(标题、作者、发布时间)。适用于品牌营销分析、热点追踪或图像处理等场景。脚本包含代理配置、接口调用和文件下载功能,并提供扩展建议如图像识别与情绪分析。适合需要高效采集小红书数据的团队或个人使用,稳定性和灵活性兼备。
958 4
|
JavaScript 前端开发 Android开发
Flutter笔记:关于WebView插件的用法(下)
Flutter笔记:关于WebView插件的用法(下)
1297 5
|
数据采集 Web App开发 监控
捕获抖音截图:如何用Puppeteer保存页面状态
随着抖音直播的兴起,实时动态和互动元素吸引了大量用户。为了捕获直播页面的实时信息,本文介绍了如何使用 Puppeteer 和代理 IP 服务,解决页面动态加载、反爬虫机制等问题,实现自动化抓取和截图保存。通过安装 Puppeteer、配置代理 IP 和编写简单脚本,可以高效地捕获抖音直播页面的状态。
650 51
|
存储 数据采集 数据挖掘
CSV vs 数据库:数据存储的最佳选择是什么
本文介绍了爬虫数据存储中CSV和数据库的优缺点,分析了两者在不同场景下的适用性。CSV简单易用、资源消耗低,适合小量数据;数据库则在处理大量数据和复杂查询时表现出色,支持并发操作。通过Python代码示例,展示了如何使用多线程和爬虫代理IP技术将百度搜索数据存储到MySQL数据库中,适用于大型项目和复杂数据分析需求。
875 2
|
SQL 设计模式 前端开发
【置顶】SAP ABAP开发实战——从入门到精通系列目录
本文章为SAP ABAP开发实战——从入门到精通系列的目录以及关于该教程的后续写作计划表
3190 0
【置顶】SAP ABAP开发实战——从入门到精通系列目录
|
缓存 前端开发 网络协议
性能优化|几个方法让图片加载更快一些
对电商网页的性能而言,图片优化是至关重要的事情,本文就此探讨了一些简单、可靠的图片优化手段。
|
数据采集 存储 数据处理
从网络请求到Excel:自动化数据抓取和保存的完整指南
本文介绍了如何使用Python自动化采集东方财富股吧的发帖信息,并将其保存到Excel中。通过代理IP、多线程和网页解析技术,规避反爬虫机制,高效抓取帖子标题和发帖时间,帮助投资者获取市场情绪和热点数据。
522 0
|
数据采集 存储
4个步骤:如何使用 SwiftSoup 和爬虫代理获取网站视频
本文介绍了如何使用SwiftSoup库和爬虫代理技术抓取网站视频资源。通过安装SwiftSoup、获取HTML内容、解析HTML以提取视频链接,以及设置爬虫代理来绕过访问限制,可以实现高效、灵活的视频资源获取。示例代码展示了一个完整的过程,包括下载并存储视频文件到设备。结合这两种技术,可以有效应对网站访问挑战,方便地获取互联网视频资源。
956 3
4个步骤:如何使用 SwiftSoup 和爬虫代理获取网站视频