之前我们都是使用HtmlAgilityPack类库来进行页面的爬取,今天我们使用一个爬虫框架。
框架名称:Clawler 参考地址
框架设计
由于我是参考的webmagic,所以整体架构上没有什么大的变化,设计图如下(图片是直接从webmagic上拿的)
- Scheduler:负责URL的调度、去重,可以实现如Queue, PriorityQueueScheduler, RedisScheduler(可用于分布式)等等
- Downloader: 负责下载HTML,可以实现如HttpDownloader, 浏览器的Downloader(WebDriver), FiddlerDownloader,本地文件Downloader等等
- PageProcesser: 负责HTML解析、目标URL的选择
- Pipeline: 负责数据的存储, 已实现文件存储, MySql存储, MySqlFile存储(脚本),MSSQL存储,MongoDb存储, 更多存储期待您的贡献
优点
- 可以使用Json定义爬虫
- 可以使用实体类+Attrbiute定义爬虫
- 自动创建数据库、数据表
- 支持 .NET CORE,可以跨平台
- 支持ADSL拨号换IP:如果所有爬虫统一部署, 可以实现单台机器同时运行多个任务拨号互不影响、或者一个路由下面多个电脑下多个任务拨号互不影响
- 支持自定义代理池
- 有管理平台
一、框架使用
我们通过HtmlAgilityPack 爬取优酷电影名的例子进行说明。
当前例子是很简单的单页面的爬取, 只爬取页面上的几个固定位置的参数内容。
我们首先来说明一下,爬虫框架的使用。框架因为定义好了四个操作流程,所以编码人员在实际过程中只要大概了解框架的使用原理即可上手操作。
用户的一般使用,采用最基本的方式。只要关心俩个类,一个是当前PageProcesser 页面的处理逻辑,一个是Pipeline爬取的数据的存储。
通过分析,我们发现一般的爬虫程序大部分内容无非也就是在梳理这俩个东西。
在框架中我们不需要关心网页的调度内容,只需要关心我们需要爬取什么内容(爬取的逻辑)和数据的存储(管道)。
放代码如下:
首先是当前页面的解析类
public class YoukuPageProcessor : BasePageProcessor
{
protected override void Handle(Page page)
{
// 利用 Selectable 查询并构造自己想要的数据对象
var totalVideoElement = page.Selectable.Select(Selectors.XPath("//*[@id='total_videonum']"));
var id = totalVideoElement.XPath("@id").GetValue();
string videoNum = totalVideoElement.GetValue();
var linqNodes = page.Selectable.Select(Selectors.XPath("//*[@id='filterPanel']/div[2]/ul")).XPath("li").Nodes();
var videoCountry = new List<string>();
foreach (var node in linqNodes)
{
string text = node.GetValue(ValueOption.InnerText);
videoCountry.Add(text);
//Console.WriteLine($"{text}");
}
var results = new YouKu()
{
id = id,
videoNum = Convert.ToInt32(videoNum),
videoCountry = videoCountry
};
// 以自定义KEY存入page对象中供Pipeline调用
page.AddResultItem("VideoResult", results);
}
}
然后是当前页面的输出类
/// <summary>
/// 优酷爬虫管道
/// </summary>
public class YoukuPipeline : BasePipeline
{
public override void Process(IEnumerable<ResultItems> resultItems, ISpider spider)
{
ResultItems result = resultItems.First();
StringBuilder builder = new StringBuilder();
YouKu entry = result.Results["VideoResult"];
builder.Append($"输出 [YouKu {entry.id}] {entry.videoNum}");
Console.WriteLine(builder.ToString());
// Other actions like save data to DB. 可以自由实现插入数据库或保存到文件
}
}
最后整合爬虫任务
/// <summary>
/// 定义处理器和管道
/// </summary>
public static void CustmizeProcessorAndPipeline()
{
// 定义采集的 Site 对象, 设置 Header、Cookie、代理等
var site = new Site();
// 添加初始采集链接
site.AddStartUrl($"http://list.youku.com/category/show/c_96_s_1_d_1_p_1.html");
Spider spider = Spider.Create(site,
// 使用内存调度
new QueueDuplicateRemovedScheduler(),
// 为优酷自定义的 Processor
new YoukuPageProcessor())
// 为优酷自定义的 Pipeline
.AddPipeline(new YoukuPipeline());
spider.Downloader = new HttpClientDownloader();
spider.ThreadNum = 1;
spider.EmptySleepTime = 3000;
// 启动爬虫
spider.Run();
}