.net core 实现简单爬虫—抓取博客园的博文列表

news/2024/7/19 10:57:08 标签: 爬虫, java, 测试

一.介绍一个Http请求框架HttpCode.Core

  HttpCode.Core 源自于HttpCode(传送门),不同的是 HttpCode.Core是基于.net standard 2.0实现的,移除了HttpCode与windows相耦合的api,且修改了异步实现,其余特性完全与HttpCode相同,大家 如果在使用中有什么问题可以查看在线文档(传送门)

HttpCode.Core完全开源,已传到github,地址:https://github.com/stulzq/HttpCode.Core

为了方便大家使用,也传到了nuget,地址:https://www.nuget.org/packages/HttpCode.Core/,在nuget中搜索 HttpCode.Core 或执行命令 Install-Package HttpCode.Core 就可以使用了。

具体的使用方法大家可以查阅在线文档,或者查看github。

简单、易用、高效 一个有态度的开源.Net Http请求框架!

二.分析抓取地址

首先使用谷歌浏览器的开发者工具,抓取博客园首页获取博文列表的地址:

 

从中我们可以分析出:

1. 请求地址  https://www.cnblogs.com/mvc/AggSite/PostList.aspx

2.请求方式  Post

3.请求数据

1 {
2     "CategoryType":"SiteHome",
3     "ParentCategoryId":0,
4     "CategoryId":808,
5     "PageIndex":3,
6     "TotalPostCount":4000,
7     "ItemListActionName":"PostList"
8

请求数据中,我们应当关心的是  PageIndex  代表的是 页数,我们可通过变换这个参数的值来获取不同页面的数据。

 我们先使用HttpCode.Core来试一试获取数据:

int pageIndex = 1;//页数
HttpHelpers httpHelpers=new HttpHelpers();
HttpItems items=new HttpItems();
items.Url = "https://www.cnblogs.com/mvc/AggSite/PostList.aspx";//请求地址
items.Method = "Post";//请求方式 post
items.Postdata = "{\"CategoryType\":\"SiteHome\"," +
                    "\"ParentCategoryId\":0," +
                    "\"CategoryId\":808," +
                    "\"PageIndex\":"+ pageIndex + "," +
                    "\"TotalPostCount\":4000," +
                    "\"ItemListActionName\":\"PostList\"}";//请求数据
HttpResults hr = httpHelpers.GetHtml(items);
Console.WriteLine(hr.Html);
Console.ReadKey();

 运行截图:

可以看到我们已经成功获取了数据,证明我们的分析是正确的。

三.解析返回的数据

刚刚我们测试接口返回的数据可以看出返回的是一堆html字符串。我们只想要博文的标题、作者、博文地址等等信息,我们不需要多余的html字符串,下面我们使用  HtmlAgilityPack 这个解析网页的组件来获得我们想要的数据。

关于这个组件的使用,博客园已经有不少介绍此组件的文档,大家可以搜索查看,使用此组件需具备xpath相关知识,我就不在此详细叙述了。

1.首先通过nuget安装 HtmlAgilityPack  组件

  打开程序包控制台

  执行命令 Install-Package HtmlAgilityPack -Version 1.5.2-beta6

2. 解析返回的数据

贴一下返回的部分数据:

 1 <div class="post_item">
 2 <div class="digg">
 3     <div class="diggit" οnclick="DiggPost('yaoxiaowen',7470460,318439,1)"> 
 4     <span class="diggnum" id="digg_count_7470460">4</span>
 5     </div>
 6     <div class="clear"></div>
 7     <div id="digg_tip_7470460" class="digg_tip"></div>
 8 </div>      
 9 <div class="post_item_body">
10     <h3><a class="titlelnk" href="http://www.cnblogs.com/yaoxiaowen/p/7470460.html" target="_blank">关于跨平台的一些认识</a></h3>                   
11     <p class="post_item_summary">
12 <a href="http://www.cnblogs.com/yaoxiaowen/" target="_blank"><img width="48" height="48" class="pfs" src="//pic.cnblogs.com/face/918357/20161122225949.png" alt=""/></a>    前段时间看了 周志明的那本 《深入理解java虚拟机》。对于 平台无关性 问题,有了一些新的认识。所以特写一篇博客来进行总结。 这是我的第一篇不针对具体技术,而只针对计算机系统和原理的博客文章,而这种话题,总是比较宽泛,而我本人的水平有限,所以我也只能泛泛的写写,思考的不对的地方,还望读者不吝批评。 ...
13     </p>              
14     <div class="post_item_foot">                    
15     <a href="http://www.cnblogs.com/yaoxiaowen/" class="lightblue">eleven_yw</a> 
16     发布于 2017-09-03 22:12 
17     <span class="article_comment"><a href="http://www.cnblogs.com/yaoxiaowen/p/7470460.html#commentform" title="2017-09-04 15:23" class="gray">
18         评论(2)</a></span><span class="article_view"><a href="http://www.cnblogs.com/yaoxiaowen/p/7470460.html" class="gray">阅读(210)</a></span></div>
19 </div>
20 <div class="clear"></div>
21 </div>
22 <div class="post_item">
23 <div class="digg">
24     <div class="diggit" οnclick="DiggPost('loseheart',7471197,375716,1)"> 
25     <span class="diggnum" id="digg_count_7471197">0</span>
26     </div>
27     <div class="clear"></div>
28     <div id="digg_tip_7471197" class="digg_tip"></div>
29 </div>      
30 <div class="post_item_body">
31     <h3><a class="titlelnk" href="http://www.cnblogs.com/loseheart/p/7471197.html" target="_blank">2017年9月3日  实现网站的权限管理</a></h3>                   
32     <p class="post_item_summary">
33 <a href="http://www.cnblogs.com/loseheart/" target="_blank"><img width="48" height="48" class="pfs" src="//pic.cnblogs.com/face/1224591/20170823222646.png" alt=""/></a>    现在各个企业管理网站对登录的账号都要进行权限管理,并且相当重要,每个账号登录进去所能看到的东西大不相同,下面是实现该功能的一个的一种方法。 需求: 权限:权限是使用者操作系统中功能模块的能力,如“角色管理”模块、“资费管 理”模块和“账单管理”模块等。通过指定权限,可将使用者的操作限定在指定的 范围 ...
34     </p>              
35     <div class="post_item_foot">                    
36     <a href="http://www.cnblogs.com/loseheart/" class="lightblue">Loseheart</a> 
37     发布于 2017-09-03 21:34 
38     <span class="article_comment"><a href="http://www.cnblogs.com/loseheart/p/7471197.html#commentform" title="" class="gray">
39         评论(0)</a></span><span class="article_view"><a href="http://www.cnblogs.com/loseheart/p/7471197.html" class="gray">阅读(354)</a></span></div>
40 </div>
41 <div class="clear"></div>
42 </div>
View Code

 从中我们不难看出每一个数据是以class=post_item的div来进行区分的,我们想要的博文地址、标题等是在这个div里面的class=post_item_body的div里面,以此类推我们可以分析出:

  • 博文标题 <div class="post_item"> | <div class="post_item_body"> | h3 | a | Text
  • 博文地址 <div class="post_item"> | <div class="post_item_body"> | h3 | a | href
  • ..以此类推

因为HtmlAgilityPack是通过xpath来解析网页的,所以现在我们要根据我们上面分析出的路径来写xpath,这里不明白xpath的可以去w3cschool学习一下,非常简单。

 下面是我写好的解析博文标题、地址和作者的代码,抓取其他信息可以自己参考试一试:

 1 //解析数据
 2 HtmlDocument doc=new HtmlDocument();
 3 //加载html
 4 doc.LoadHtml(hr.Html);
 5 
 6 //获取 class=post_item_body 的div列表
 7 HtmlNodeCollection itemNodes = doc.DocumentNode.SelectNodes("div[@class='post_item']/div[@class='post_item_body']");
 8 
 9 //循环根据每个div解析我们想要的数据
10 
11 foreach (var item in itemNodes)
12 {
13     //获取包含博文标题和地址的 a 标签
14     var nodeA = item.SelectSingleNode("h3/a");
15     //获取博文标题
16     string title = nodeA.InnerText;
17     //获取博文地址 a标签的 href 属性
18     string url = nodeA.GetAttributeValue("href", "");
19 
20     //获取包含作者名字的 a 标签
21     var nodeAuthor = item.SelectSingleNode("div[@class='post_item_foot']/a[@class='lightblue']");
22     string author = nodeAuthor.InnerText;
23 
24     Console.WriteLine($"标题:{title} | 作者:{author} | 地址:{url}");
25 }

 运行截图:

 

四.循环抓取多个分页

前面我们分析出请求参数中的 PageIndex  是页数,分析单个页面的代码我们也写出来来,那么我们可以通过循环递增页数,来达到抓取不同分页数据的要求。

贴一下完整的代码

 1 int pageIndex = 1;//页数
 2 int maxPageIndex = 10;//最大页数
 3 HttpHelpers httpHelpers=new HttpHelpers();
 4 
 5 for (int i = 0; i < maxPageIndex; i++)
 6 {
 7     HttpItems items = new HttpItems();
 8     items.Url = "https://www.cnblogs.com/mvc/AggSite/PostList.aspx";//请求地址
 9     items.Method = "Post";//请求方式 post
10     items.Postdata = "{\"CategoryType\":\"SiteHome\"," +
11                         "\"ParentCategoryId\":0," +
12                         "\"CategoryId\":808," +
13                         "\"PageIndex\":" + (i+1) + "," + //因为i从0开始 所以此处我们要加1
14                         "\"TotalPostCount\":4000," +
15                         "\"ItemListActionName\":\"PostList\"}";//请求数据
16     HttpResults hr = httpHelpers.GetHtml(items);
17 
18     //解析数据
19     HtmlDocument doc = new HtmlDocument();
20     //加载html
21     doc.LoadHtml(hr.Html);
22 
23     //获取 class=post_item_body 的div列表
24     HtmlNodeCollection itemNodes = doc.DocumentNode.SelectNodes("div[@class='post_item']/div[@class='post_item_body']");
25 
26     Console.WriteLine($"第{i+1}页数据:");
27 
28     //循环根据每个div解析我们想要的数据
29     foreach (var item in itemNodes)
30     {
31         //获取包含博文标题和地址的 a 标签
32         var nodeA = item.SelectSingleNode("h3/a");
33         //获取博文标题
34         string title = nodeA.InnerText;
35         //获取博文地址 a标签的 href 属性
36         string url = nodeA.GetAttributeValue("href", "");
37 
38         //获取包含作者名字的 a 标签
39         var nodeAuthor = item.SelectSingleNode("div[@class='post_item_foot']/a[@class='lightblue']");
40         string author = nodeAuthor.InnerText;
41         //输出数据
42         Console.WriteLine($"标题:{title} | 作者:{author} | 地址:{url}");
43     }
44 
45     //每抓取一页数据 暂停三秒
46     Thread.Sleep(3000);
47 }
48             
49 Console.ReadKey();

 运行截图:

一个简单的.net core实现的简单爬虫就此完成!

 Demo下载


http://www.niftyadmin.cn/n/979146.html

相关文章

ssm项目项目依赖引入问题

先说一说起因&#xff0c;今天上午写一个接口时返回了自定义结果类 结果报出了没有将返回结果类R 转换成 json 的类&#xff0c;由于我写自定义返回结果集不多&#xff0c;所以问题并没有准确定位&#xff0c;以为是自己代码的问题。 在网上查阅后&#xff0c;发现报这个错误的…

硅谷面临着技术外流

This appeared in The Millennial Source这出现在千禧年的来源 For years, commentators have written about the possibility of a “tech exodus” from Silicon Valley spurred by high rental prices and the difficulty of achieving homeownership in the Bay Area, eve…

Salesforce即将推出Einstein人工智能CRM平台

Salesforce首席执行官Marc Benioff本周三向投资者表示&#xff0c;在即将举行的Dreamforce大会上Salesforce将展示一种独一无二的人工智能CRM平台&#xff0c;该平台结合了Salesforce最近几年收购的多项技术。 在公布了2017财年第二季度业绩的同时&#xff0c;Benioff也在财报电…

《C++语言基础》实践项目——链表类及其应用

返回&#xff1a;贺老师课程教学链接 【项目 - 链表类】动态链表也是程序设计中的一种非常有用的数据结构。可以说&#xff0c;是否能够理解有关操作的原理&#xff0c;决定了你是否有资格称为“科班”出身。在后续的专业基础课中&#xff0c;相关的内容还会从不同的角度&#…

编程心得

解数独&#xff08;续&#xff09; 请参考编程解决数独问题&#xff0c;效率和简洁并存 很少使用类处理问题&#xff0c;就在解数独上试着用了一下&#xff0c;看看效果怎么样&#xff0c;其实也都差不多&#xff0c;直接看代码吧。 """ The program is debug…

Hibernate强制清除Session缓存 Clear与Flush方法 FlushMode设置

一、Session中FlushMode的设置&#xff1a; 在事务开启前设置FlushMode属性&#xff0c;方法session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL)。 FlushMode有5个值可选&#xff1a;Always:任何代码都会Flush、AUTO:默认方式–自动、Commit:COMMIT时、Never:始…

寻道时间占主导_3G尚未主导5G的3个原因

寻道时间占主导T-Mobile is the mid-band leader on 5G in the US. So what’s holding it back from 5G supremacy? We assembled a Twitter brain trust to explain.T-Mobile是美国5G的中频领导者。 那么&#xff0c;是什么阻碍了5G霸主地位呢&#xff1f; 我们组建了一个Tw…

maven中的依赖显示unknown .imi文件的作用

如图 检查.iml文件是不是被误删了 imi文件的作用&#x1f525; iml文件是IntelliJIDEA自动创建的模块文件&#xff0c;用于Java应用开发&#xff0c;存储一些模块开发相关的信息,比如一个Java组件&#xff0c;插件组件&#xff0c;Maven组件等等&#xff0c;还可能会存储一些模…