接下来一段时间,我会花些时间研究C#玩转爬虫的方法及其实践。

话不多说,开始吧~

一般来说:

设计并实现一个爬虫的步骤是:

模拟登录 -> 模拟发送request请求 -> 取回response数据 -> 提取所需信息并将其进行重新组织 -> 存入DB或文件中 -> 后期处理或展示

流程图

当然,有时还需要适当地应对所抓取目标站点的反爬虫策略,也就是大家常说的反反爬

下文以抓取豆瓣音乐为例来具体说明:

比如,我们在豆瓣音乐中搜索"摇滚"后爬取相关内容,然后写入csv文件中。

目标网址是:

https://music.douban.com/tag/摇滚?start=0&type=T

抓取大概分为如下几个步骤:

获取页数

  • 发请求

每一页中都可以看到总的页数,直接取第1页的就好。

    byte[] buffer = webclient.DownloadData("https://music.douban.com/tag/%E6%91%87%E6%BB%9A?start=0&type=T");// utf-8, gb2312, gbk, utf-1......string html = System.Text.Encoding.GetEncoding("utf-8").GetString(buffer);

借助以上两行代码,就可以看到该网址Response的HTML字符串(debug时上面一行代码中html的值)为:

  • 使用正则表达式匹配到页数

我们选用模式串 ">[0-9][0-9]{0,}</a>" 进行匹配,由于下面的页码是从第一页算起的,选最大页数就是总页数。

相应的函数GetTotalCount如下:

        private static int GetTotalCount(System.Net.WebClient webclient, int startIdx){//html下载/* https://music.douban.com/tag/%E6%91%87%E6%BB%9A?start=0&amp;type=T  */byte[] buffer = webclient.DownloadData("https://music.douban.com/tag/%E6%91%87%E6%BB%9A?start=" + startIdx + "&amp;type=T");// utf-8, gb2312, gbk, utf-1......string html = System.Text.Encoding.GetEncoding("utf-8").GetString(buffer);MatchCollection pageCount_matches = new Regex("&gt;[0-9][0-9]{0,}&lt;/a&gt;").Matches(html);if (pageCount_matches.Count == 0)return 0;string tempPageNum = pageCount_matches[pageCount_matches.Count - 1].Value;int.TryParse(tempPageNum.Replace("&lt;/a&gt;", string.Empty).Substring(1), out int lastPageNum);return lastPageNum;}

获取当前页的数据

  • 发请求

用与上一步相同的方法

byte[] buffer = webclient.DownloadData("https://music.douban.com/tag/%E6%91%87%E6%BB%9A?start=0&amp;type=T");// utf-8, gb2312, gbk, utf-1......
string html = System.Text.Encoding.GetEncoding("utf-8").GetString(buffer);

debug时可得到当前页对应的HTML字符串:

  • 使用正则表达式匹配到每一天记录

我们选用模式串 "<p class=\"pl\">([\\s\\S]*?)</p>" 进行匹配,可得到如下格式的内容:

刺猬 / 2018-01-08 / 单曲 / 数字(Digital) / 摇滚

接着进行split可得到一个记录的各个属性。

具体的函数GetCurrentPageRecords如下:

    private static void GetCurrentPageRecords(System.Net.WebClient webclient, int startIdx){byte[] buffer = webclient.DownloadData("https://music.douban.com/tag/%E6%91%87%E6%BB%9A?start=" + startIdx + "&amp;type=T");// utf-8, gb2312, gbk, utf-1......string html = System.Text.Encoding.GetEncoding("utf-8").GetString(buffer);// Console.WriteLine(html);// html分析// 通过正则获取到需要的数据// &lt;p class="pl"&gt;刺猬 / 2018-01-08 / 单曲 / 数字(Digital) / 摇滚&lt;/p&gt;MatchCollection musicItem_matches = new Regex("&lt;p class=\"pl\"&gt;([\\s\\S]*?)&lt;/p&gt;").Matches(html);int count = musicItem_matches.Count;for (int i = 0; i &lt; count; i++){string item = musicItem_matches[i].Result("$1");string[] strArr = item.Trim().Split('/');Record record = new Record{SongName = strArr[0],Date = strArr.ElementAtOrDefault(1),Album = strArr.ElementAtOrDefault(2),Type = strArr.ElementAtOrDefault(3),Topic = strArr.ElementAtOrDefault(4)};_records.Add(record);}}

获取所有页的数据

  • 循环修改url中start的值

https://music.douban.com/tag/摇滚?start=0&type=T

第一页的start=0,每页20条,于是后面每一页的start是前一页start的值+20

  • 发请求

  • 将每页的数据加入到Array或List中

写入csv

  • 在VS的NuGet包管理器中为当前项目引入CSVHelper.

  • 将一条记录封装成一个类Record

Record.cs

using System;
using System.Collections.Generic;
using System.Text;namespace CsSpider
{public class Record{public string SongName { get; set; }public string Date { get; set; }public string Album { get; set; }public string Type { get; set; }public string Topic { get; set; }}
}// 举例: 万能青年旅店 / 2010-11-12 / 专辑 / CD / 摇滚
  • 使用CSVHelper把获得的所有数据写入到csv中

    if (_records.Count &gt; 0){var writer = new StreamWriter(_filename);using (var csv = new CsvWriter(writer)){csv.WriteRecords(_records);Console.WriteLine("导出完成.");}}

解决乱码问题

只需要给上述writer设置Encoding即可~

        if (_records.Count &gt; 0){var writer = new StreamWriter(_filename, false, System.Text.Encoding.UTF8);  // 设置Encoding,防止乱码using (var csv = new CsvWriter(writer)){csv.WriteRecords(_records);Console.WriteLine("导出完成.");}}

运行结果

最后得到的CSV文件如下:

接下来,会发现一个问题:

如果多执行几次,前面的HTML字符串会变成下面这种内容:

&lt;script&gt;var d=[navigator.platform,navigator.userAgent,navigator.vendor].join("|");window.location.href="https://sec.douban.com/a?c=3d001f&amp;d="+d+"&amp;r=https%3A%2F%2Fmovie.douban.com%2Fsubject%2F26590960%2F";&lt;/script&gt;

说明此时,你触发了豆瓣的反作弊功能。如果再多执行几次,会出现 403 Error.

解决办法是模拟登录,这个留在下一篇文章再说,敬请关注!

CsSpider · yanglr/csharp_spiderhttps://github.com/yanglr/csharp_spider/tree/master/spider-test/CsSpider

欢迎star、fork或拉取使用和研究!!!

你点的每一个"在看",

我都当成了喜欢!

.NET Core玩转爬虫系列之借助正则表达式入门篇相关推荐

  1. .NET Core实战项目之CMS 第四章 入门篇-Git的快速入门及实战演练

    写在前面 上篇文章.NET Core实战项目之CMS 第三章 入门篇-源码解析配置文件及依赖注入我带着大家通过分析了一遍ASP.NET Core的源码了解了它的启动过程,然后又带着大家熟悉了一遍配置文 ...

  2. .NET Core实战项目之CMS 第六章 入门篇-Vue的快速入门及其使用

    写在前面 上面文章我给大家介绍了Dapper这个ORM框架的简单使用,大伙会用了嘛!本来今天这篇文章是要讲Vue的快速入门的,原因是想在后面的文章中使用Vue进行这个CMS系统的后台管理界面的实现.但 ...

  3. .NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了

    写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ...

  4. .NET Core实战项目之CMS 第三章 入门篇-源码解析配置文件及依赖注入

    写在前面 上篇文章我给大家讲解了ASP.NET Core的概念及为什么使用它,接着带着你一步一步的配置了.NET Core的开发环境并创建了一个ASP.NET Core的mvc项目,同时又通过一个实战 ...

  5. [Python爬虫] scrapy爬虫系列 一.安装及入门介绍

    前面介绍了很多Selenium基于自动测试的Python爬虫程序,主要利用它的xpath语句,通过分析网页DOM树结构进行爬取内容,同时可以结合Phantomjs模拟浏览器进行鼠标或键盘操作.但是,更 ...

  6. python爬虫基础教程1_Python爬虫系列(一)入门教学

    " 启 大家好,我是新来的小编小周.今天给大家带来的是python爬虫入门, 文章以简为要,引导初学者快速上手爬虫.话不多说,我们开始今天的内容. 在初步学习爬虫之前,我们先用一个例子来看看 ...

  7. 【Python3.6+Django2.0+Xadmin2.0系列教程之一(入门篇-上)】环境搭建及项目创建

    由于工作需要,接触了大半年时间的Django+xadmin框架,一直没空对这块对进行相关的梳理.最近在同事的怂恿下,就在这分享下笔者的学习及工作经验吧. 好了,话不多说,下面开始进入正题: 转载请注明 ...

  8. QCC305x系列开发教程(入门篇)之1.2-安装开发中需要配套软件

    目录 1.MDE安装 2.ADK_Toolkit安装 3.QACT安装 4.BlueSuite安装 5.GAIA_Client安装(安卓版) 查看全部文章:本系列文章全部汇总

  9. RK3399平台开发系列讲解(内核入门篇)1.1、通过sysfs清楚了解设备的系统状况

    =>返回专栏总目录<= 文章目录 1.不敢高声语,恐惊天上人:sysfs目的 2.窥一斑而知全豹:sysfs目录介绍 3.千丝万缕:sysfs中要素的关系 4.数据观星:sysfs中相关结 ...

最新文章

  1. Windows Phone实用开发技巧(32):照片角度处理
  2. java 集合差运算_用一个参数的JAVA程序实现集合的交并差运算
  3. 047_Divider分割线
  4. 【人物】徐小平:既然做老大,你就得让兄弟们有肉吃
  5. VTK:可视化之HanoiIntermediate
  6. 大厂疯传!Python+商业数据分析+数据可视化教程(附项目案例)
  7. 如何让Windows任务栏显示多个不同时区的时钟
  8. final关键字_Java面试-谈谈对final关键字的理解
  9. Unity3d 新建xml 读取xml
  10. Bash shell脚本打印出正在执行的命令
  11. 一种调用dll的巧妙方法
  12. linux格式化nfs,NFS协议详解与配置实现
  13. 一个Https网站发送Http的 ajax请求的解决方法
  14. ReSharper卸载后Visual Studio的快捷键和智能提示消失
  15. 除了定时器,真的没法在Simulation Node 类型的CAPL节点中实现延时了吗?
  16. metabase开源BI
  17. Linux错误码汇总
  18. 工训赛:从参赛到“弃赛”
  19. pygal画世界地图
  20. 【POJ 1788 --- Building a New Depot】

热门文章

  1. ORACLE备份中的压缩
  2. 如何在不支付Adobe Photoshop费用的情况下处理Camera Raw
  3. file协议 控制面板_如何在Windows File Explorer导航窗格中显示控制面板和回收站
  4. google hdr+_更好的隐私权控制使Google+死了
  5. C#如何用正则表达式截取https和带端口的域名
  6. 转: javascript技术栈
  7. hdu 4049 Tourism Planning [ 状压dp ]
  8. 金山安全实验室公布中国互联网六大类钓鱼网站
  9. 哎,最近心情非常烦乱!
  10. 【招聘(北京武汉)】北京高远华信科技 .NET 高级工程师