代碼下載地址:
https://github.com/happlyfox/FoxCrawler/tree/master/%E5%AD%A6%E4%B9%A0%E7%A4%BA%E4%BE%8B/YouKuCrawler/YouKuDotnetSpider2Async
基於文章三我們實現了爬蟲框架單頁面應用程序的代碼,那麼在這一章節我們將使用框架進行內容分頁和多線程的操作
首先附上代碼
public class YouKuCrawer { private static readonly string _url = "http://list.youku.com/category/video/c_0.html"; /// <summary> /// 得到所有的類別 /// </summary> public static List<VideoType> GetVideoTypes() { //加載web內容 var web = new HtmlWeb(); var doc = web.Load(_url); //內容解析-獲得所有的類別 var allTypes = doc.DocumentNode.SelectNodes("//*[@id='filterPanel']/div/ul/li/a").ToList(); //類別列表中去掉【全部】這個選項 var typeResults = allTypes.Where((u, i) => { return i > 0; }).ToList(); var reList = new List<VideoType>(); foreach (var node in typeResults) { var href = node.Attributes["href"].Value; reList.Add(new VideoType { Code = href.Substring(href.LastIndexOf("/") + 1, href.LastIndexOf(".") - href.LastIndexOf("/") - 1), Name = node.InnerText }); } return reList; } /// <summary> /// 得到當前類別的總頁數 /// </summary> public static int GetPageCountByCode(string code) { var web = new HtmlWeb(); var doc = web.Load($"http://list.youku.com/category/show/{code}.html"); //分頁列表 var pageList = doc.DocumentNode.CssSelect(".yk-pages li").ToList(); //得到倒數第二項 var lastsecond = pageList[pageList.Count - 2]; return Convert.ToInt32(lastsecond.InnerText); } }
因爲所有的頁面內容都相同,只是網站地址(url)不同,所以我首先得到所有的地址集合,然後賦給框架,讓框架識別。
// 添加初始採集鏈接 // 定義採集的 Site 對象, 設置 Header、Cookie、代理等 var site = new Site { EncodingName = "UTF-8" }; foreach (var node in YouKuCrawer.GetVideoTypes()) { //得到當前類別總分頁數 var pageCount = YouKuCrawer.GetPageCountByCode(node.Code); for (int pageIndex = 1; pageIndex <= pageCount; pageIndex++) { site.AddStartUrl($"http://list.youku.com/category/show/{node.Code}_s_1_d_1_p_{pageIndex}.html"); } }
首先定時採集的site對象,然後site對象添加需要解析的相同的url。在上述操作完成後,我們開始進行“解析器”類和“管道”類的書寫。
解析器類
public class YoukuPipeline : BasePipeline { public override void Process(IEnumerable<ResultItems> resultItems, ISpider spider) { var resultItem= resultItems.FirstOrDefault(); foreach (VideoContent entry in resultItem.GetResultItem("VideoResult")) { Console.WriteLine($"{entry.Title}\t\t{entry.Href}"); } } }
管道類
public class YoukuPipeline : BasePipeline { public override void Process(IEnumerable<ResultItems> resultItems, ISpider spider) { var resultItem= resultItems.FirstOrDefault(); foreach (VideoContent entry in resultItem.GetResultItem("VideoResult")) { Console.WriteLine($"{entry.Title}\t\t{entry.Href}"); } } }
最後對定義的內容進行整理
public static void CustmizeProcessorAndPipeline() { // 定義採集的 Site 對象, 設置 Header、Cookie、代理等 var site = new Site { EncodingName = "UTF-8" }; // 添加初始採集鏈接 foreach (var node in YouKuCrawer.GetVideoTypes()) { //得到當前類別總分頁數 var pageCount = YouKuCrawer.GetPageCountByCode(node.Code); for (int pageIndex = 1; pageIndex <= pageCount; pageIndex++) { site.AddStartUrl($"http://list.youku.com/category/show/{node.Code}_s_1_d_1_p_{pageIndex}.html"); } } Spider spider = Spider.Create(site, // 使用內存調度 new QueueDuplicateRemovedScheduler(), // 爲優酷自定義的 Processor new YoukuPageProcessor()) //爲優酷自定義的 Pipeline .AddPipeline(new YoukuPipeline()); spider.Downloader = new HttpClientDownloader(); spider.ThreadNum = 10; spider.EmptySleepTime = 3000; // 啓動爬蟲 spider.Run(); }
線程定義
spider.ThreadNum = 10;
只需要通過自己的要求來進行賦值,框架自動識別內容優化線程操作。很方便