C#攻克反爬虫之代理IP爬取

编程入门 行业动态 更新时间:2024-10-05 01:14:54

C#攻克反<a href=https://www.elefans.com/category/jswz/34/1770264.html style=爬虫之代理IP爬取"/>

C#攻克反爬虫之代理IP爬取

目前很多大型网站在反爬虫时采取IP限制策略,限制同一个IP的请求频率及次数,或者同一IP在达到请求次数后强制登陆验证等。此时我们就需要用到代理IP来突破限制,此篇我们介绍通过DotnetSpider框架爬取西刺高匿代理IP的过程。

DotnetSpider框架简介

DotnetSpider是 core开发的开源爬虫项目,基本开箱即用,对于爬虫各个部分的封装已经比较成熟,github下载地址:

下载下来运行几个示例基本就知道如何使用了,示例在DotnetSpider.Sample解决方案下面,下面我们看一下例子中的CnblogsSpider。
CnblogsSpider在被调用时会执行Initialize()方法做一些爬虫配置的初始化,如下:

		protected override async Task Initialize(){NewGuidId();Depth = 3;AddDataFlow(new ListNewsParser()).AddDataFlow(new ConsoleStorage());await AddRequests("/");}

其中最重要的包含三部分,ListNewsParser,ConsoleStorage和最后的AddRequests。ListNewsParser是定义爬虫如何解析我们要爬取的网页以及返回怎样的一个结果,ConsoleStorage是定义爬虫如何保存我们爬取的结果,AddRequests则是指定爬虫爬取的目标url。下面我们分别看一下ListNewsParser和ConsoleStorage的代码。

class ListNewsParser : DataParser{public ListNewsParser(){Required = DataParserHelper.CheckIfRequiredByRegex("news\\blogs\\/n/page");// 如果你还想翻页则可以去掉注释//FollowRequestQuerier =//	BuildFollowRequestQuerier(DataParserHelper.QueryFollowRequestsByXPath(".//div[@class='pager']"));}protected override Task<DataFlowResult> Parse(DataFlowContext context){var news = context.Selectable.XPath(".//div[@class='news_block']").Nodes();foreach (var item in news){var title = item.Select(Selectors.XPath(".//h2[@class='news_entry']")).GetValue(ValueOption.InnerText);var url = item.Select(Selectors.XPath(".//h2[@class='news_entry']/a/@href")).GetValue();var summary = item.Select(Selectors.XPath(".//div[@class='entry_summary']")).GetValue(ValueOption.InnerText);var views = item.Select(Selectors.XPath(".//span[@class='view']")).GetValue(ValueOption.InnerText).Replace(" 人浏览", "");var request = CreateFromRequest(context.Response.Request, url);request.AddProperty("title", title);request.AddProperty("summary", summary);request.AddProperty("views", views);context.AddExtraRequests(request);}return Task.FromResult(DataFlowResult.Success);}}

其中关键方法是Parse(),在Parse()中通过Xpath取得目标网页上的信息,并最终存入字典title,summary,views。如果我们要写爬虫可以新建一个类继承自DataParser类,然后实现方法Parse,在Parse()中通过Xpath或其它的一些途径获取想要的信息并封装成我们想要的结果。

	/// <summary>/// 控制台打印解析结果(所有解析结果)/// </summary>public class ConsoleStorage : StorageBase{/// <summary>/// 根据配置返回存储器/// </summary>/// <param name="options">配置</param>/// <returns></returns>public static ConsoleStorage CreateFromOptions(SpiderOptions options){return new ConsoleStorage();}protected override Task<DataFlowResult> Store(DataFlowContext context){var items = context.GetData();Console.WriteLine(JsonConvert.SerializeObject(items));return Task.FromResult(DataFlowResult.Success);}}

ConsoleStorage 是定义如何输出保存我们在DataParser中获取的数据,关键方法是Store(),我们可以看到里面是将结果对象序列化为Json字符串并在控制台中输出了。目前DotnetSpider中已经封装了一些常用的保存类,如控制台输出,输出保存JSON文件,保存到Mysql/Sqlserver等,可以在DotnetSpider解决方案下DataFlow-Storage文件夹下看到。同样地我们可以自定义自己的存储方式,只需要继承StorageBase类并实现Store(),在方法中定义存储在文件,数据库或者缓存中。

西刺代理IP网页分析爬取

西刺代理官网地址/
我们先通过F12查看我们要获取的代理IP和端口的元素位置

页面是有分页的,访问时在url后面评上页数就是访问指定的页数。所有的数据都在页面中一个id='ip_list’的table中,这样我们只需要爬取这个table并取得其中每一行的数据即可。下面开始编写DataParser类。

		class MyParser : DataParser<IPDataEntry>{protected override Task<DataFlowResult> Parse(DataFlowContext context){var typeName = typeof(IPDataEntry).FullName;//首先取得table元素var table = context.Selectable.Select(Selectors.XPath(".//table[@id='ip_list']")).GetValue();//取得table行数var rowcount = System.Text.RegularExpressions.Regex.Matches(table, @"</tr>").Count;//遍历table每一行,取得其中的ip和portfor (int i = 2; i <= rowcount; i++){//IP和端口分别在第二列和第三列var IP = context.Selectable.Select(Selectors.XPath($".//table[@id='ip_list']//tr[{i}]/td[2]/text()")).GetValue();var PORT = context.Selectable.Select(Selectors.XPath($".//table[@id='ip_list']//tr[{i}]/td[3]/text()")).GetValue();ProxyDataItem proxy = new ProxyDataItem(){IpAddress = IP,Port = PORT};//验证抓取到的ip和端口是否可用,可用则加入到结果中if (ValidateHelper.ValidateProxy(proxy)){context.AddData(typeName + (i - 1),new IPDataEntry{IP = IP,PORT = PORT});//Console.WriteLine($"{IP}:{PORT}");}}return Task.FromResult(DataFlowResult.Success);}}

在上面的MyParser类中我们对table中的IP和端口进行了爬取,并且简单验证了代理IP的可用信,将可用的IP构建成了IPDataEntry就存放在结果中。下面我们需要编写Storage类用来保存结果,由于代理IP存在不稳定性,经常失效,所以我们不做持久化存储,就存在Redis缓存中,对Redis缓存及使用不太清楚的可以看我的上一篇博文C# Redis使用及帮助类
下面是RedisStorage类:

	public class RedisStorage : StorageBase{/// <summary>/// 根据配置返回存储器/// </summary>/// <param name="options"></param>/// <returns></returns>public static RedisStorage CreateFromOptions(SpiderOptions options){return new RedisStorage();}protected override Task<DataFlowResult> Store(DataFlowContext context){RedisHelper redisHelper = new RedisHelper("localhost");var items = context.GetData();var list = new List<IPDataEntry>();foreach (var item in items){list.Add(item.Value as IPDataEntry);}//先将缓存中的旧数据情掉redisHelper.delKey("IPDATA");//将新抓取的数据存入缓存redisHelper.addList<IPDataEntry>("IPDATA",list);return Task.FromResult(DataFlowResult.Success);}}

最后我们在DotnetSpider.Sample解决方案的Program.cs中调用我们编写的IPDataSpider并运行。下面我们看下爬虫运行完写入缓存中的代理IP

以上就是本篇的所有内容,有需要代码的可以前往下载

更多推荐

C#攻克反爬虫之代理IP爬取

本文发布于:2024-02-07 05:27:51,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1753555.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:爬虫   IP

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!