頁面數據採集——網絡爬蟲實戰(ASP.NET Web 博客園為例)
- 2020 年 12 月 25 日
- 筆記
年輕人不講武德
相信很多朋友都有這種苦惱:自己的文章被搬運了!
你上午在博客園、CSDN、知乎、簡書等平台發佈的文章,下午去百度搜索出來一大堆一模一樣的內容出來
有武德的給你【標明出處】(標明文章來自哪兒,附上鏈接),沒武德的不僅沒標明出處,他還自己表示為原創(內心一萬頭草泥馬在奔騰~)。
文章搬運我個人是歡迎的,但是需要註明出處。對於這種情況很難說,褒貶不一,個人看法不同,
對於我來說,肯定是想要更多人看到我的文章啦(內心竊喜~)。
比如下圖左邊第一個是我2019年2月份發佈的一篇文章到現在為止搬運次數超過50+了(能被別人搬運也是對自己的一種肯定),
釋語
對於外行的朋友來說,感覺雲里霧裡的,不明覺厲。
對於內行的朋友來說,就是一個簡單的爬蟲,獲取到網頁內容後重新發佈一下而已。
什麼是數據採集?
數據採集(也稱為網絡數據提取或網頁爬取)是指從網上獲取數據,並將獲取到的數據轉化為結構化的數據,最終可以將數據存儲到本地計算機或數據庫的一種技術。
什麼是網絡爬蟲?
網絡爬蟲(又稱為網頁蜘蛛,網絡機械人,在FOAF社區中間,更經常的稱為網頁追逐者),是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本。另外一些不常使用的名字還有螞蟻、自動索引、模擬程序或者蠕蟲。
網絡爬蟲的分類
網絡爬蟲按照系統結構和實現技術,大致可以分為以下幾種類型:
- 通用網絡爬蟲(General Purpose Web Crawler)、
- 聚焦網絡爬蟲(Focused Web Crawler)、
- 增量式網絡爬蟲(Incremental Web Crawler)、
- 深層網絡爬蟲(Deep Web Crawler)。
實際的網絡爬蟲系統通常是幾種爬蟲技術相結合實現的。
專業介紹:百度百科。
爬蟲步驟
- 指定url;
- 基於request模塊發起請求;
- 獲取響應對象返回的數據;
- 解析返回的數據(正則解析、Xpath解析、BeautifulSoup解析等);
- 數據持久化存儲;
接下來我們結合理論進行一下操作,以獲取博客園文章為例,這裡使用正則解析。
實例操作(採集博客園文章:指定鏈接採集)
開發環境
操作系統:windows7 x64;
開發工具:Visual Studio 2017
項目名稱:ASP.NET Web 應用程序(.Net Framework)
數據庫:SqlServer2012
實例分析
1、建立一個ASP.NET Web 應用程序項目,命名為Reptiles。
項目創建成功後,我們先去分析一下數據結構,可以根據request返回的請求分析,但是我這裡的目標是html頁面,所以直接F12進行分析,
我們分析後找到文章標題,文章內容,分別如下:
通過上面的分析,就可以先寫出正則表達式:
//文章標題
Regex regTitle = new Regex(@”<a\sid=””cb_post_title_url””[^>]*?>(.*?)</a>”, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
//文章內容
Regex regContent = new Regex(@”<div\sid=””cnblogs_post_body””[^>]*?>(.*?)</div>”, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
完整代碼放在最後面,直接拷貝就可以使用;
查看一下運行結果:
注意,這裡沒有持久化入庫,有需要的同學根據自己的需要自行入庫即可。
實例操作(採集博客園文章:批量採集)
批量採集和指定url採集差不多,批量採集需要先獲取指定頁面(這裡以博客園首頁為例),
獲取頁面上面的url去獲取下面的內容。同樣的,我們先分析一下頁面數據結構,如下:
通過上面的分析,就可以先寫出正則表達式:
//標題div
Regex regBody = new Regex(@”<div\sclass=””post-item-text””>([\s\S].*?)</div>”, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
//a標籤 文章標題
Regex regTitle = new Regex(“<a[^>]*?>(.*?)</a>”, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
//文章標題URL
string regURL = @”(?is)<a[^>]*?href=([‘””\s]?)(?<href>[^'””\s]*)\1[^>]*?>”;
代碼放後面,我們先看一下運行結果:
代碼展示
註:建立好相應的控制器和view視圖後,直接拷貝即可使用
- 批量採集視圖:About
- 指定鏈接採集視圖:Contact
- 控制器:HomeController
【 指定鏈接採集】前端代碼
<!--這個jQuery可以引用一個在線的使用,我這裡是本地的--> <script src="~/Scripts/jquery-3.3.1.min.js"></script> <div style="margin-top:40px;font-family:'Microsoft YaHei';font-size:18px; "> <h1>指定鏈接採集</h1> <hr /> <div style="height:60px;width:100%;border:1px solid gray;padding:10px"> <input style="width:900px;height:100%;max-width:900px;" id="Url" placeholder="這裡是文章URL鏈接" /> <a href="javascript:void(0)" onclick="GetHtml()">採集數據</a> </div> <div id="content" style="overflow:auto;height:600px;width:100%;border:1px solid gray;"> <!--標題--> <h1 class="postTitle"></h1> <div class="postBody"></div> <!--內容--> </div> </div> <script> function GetHtml() { $.ajax({ url: "/Home/GetHtml", data: { Url: $("#Url").val() }, type: "POST", dataType: "json", success: function (data) { var data = eval("(" + data + ")"); if (data.length > 0) { $(".postTitle").html(data[0].ArticleTitle); $(".postBody").html(data[0].ArticleContent); } } }); } </script>
【 批量採集】前端代碼
<!--這個jQuery可以引用一個在線的使用,我這裡是本地的--> <script src="~/Scripts/jquery-3.3.1.min.js"></script> <div style="margin-top:40px;font-family:'Microsoft YaHei';font-size:18px; "> <h1>批量採集</h1> <hr /> <div style="height:60px;width:100%;border:1px solid gray;padding:10px"> 點我進行<a href="javascript:void(0)" style="font-size:24px;" onclick="GetHtml()">【採集數據】</a> </div> <div id="content" style="overflow:auto;height:600px;width:100%;border:1px solid gray;"> <!--標題--> <div id="post_list"></div> </div> </div> <script> function GetHtml() { $.ajax({ url: "/Home/GetHtml", data: { Url: $("#Url").val() }, type: "POST", dataType: "json", success: function (data) { var data = eval("(" + data + ")"); if (data.length > 0) { var html_text = ""; for (var i = 0; i < data.length; i++) { html_text += '<div class="post-item-text">' + data[i].ArticleTitle2+'</div>'; } $("#post_list").html(html_text); } } }); } </script>
控制器後端代碼:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Web; using System.Web.Mvc; namespace Reptiles.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } //數據採集 public JsonResult GetHtml(string Url) { CnblogsModel result = new CnblogsModel(); List<CnblogsModel> HttpGetHtml = new List<CnblogsModel>(); if (string.IsNullOrEmpty(Url)) HttpGetHtml = GetUrl(); else HttpGetHtml = GetUrl(Url); var strList=Newtonsoft.Json.JsonConvert.SerializeObject(HttpGetHtml); return Json(strList, JsonRequestBehavior.AllowGet); } #region 爬蟲 #region 批量採集 //得到首頁的URL public static List<CnblogsModel> GetUrl() { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("//www.cnblogs.com/"); request.Method = "GET"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.UserAgent = " Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream stream = response.GetResponseStream(); StreamReader sr = new StreamReader(stream); string articleContent = sr.ReadToEnd(); List<CnblogsModel> list = new List<CnblogsModel>(); #region 正則表達式 //標題div Regex regBody = new Regex(@"<div\sclass=""post-item-text"">([\s\S].*?)</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); //a標籤 文章標題 Regex regTitle = new Regex("<a[^>]*?>(.*?)</a>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); //文章標題URL string regURL = @"(?is)<a[^>]*?href=(['""\s]?)(?<href>[^'""\s]*)\1[^>]*?>"; #endregion MatchCollection mList = regBody.Matches(articleContent); CnblogsModel model = null; String strBody = String.Empty; for (int i = 0; i < mList.Count; i++) { model = new CnblogsModel(); strBody = mList[i].Groups[1].ToString(); MatchCollection aList = regTitle.Matches(strBody); int aCount = aList.Count; //文章標題 model.ArticleTitle = aList[0].Groups[1].ToString(); model.ArticleTitle2 = aList[0].Groups[0].ToString(); //文章鏈接 var item = Regex.Match(aList[0].Groups[0].ToString(), regURL, RegexOptions.IgnoreCase); model.ArticleUrl = item.Groups["href"].Value; //根據文章鏈接獲取文章內容 model.ArticleContent = GetConentByUrl(model.ArticleUrl); list.Add(model); } return list; } //根據URL得到文章內容 public static string GetConentByUrl(string URL) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); request.Method = "GET"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.UserAgent = " Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream stream = response.GetResponseStream(); StreamReader sr = new StreamReader(stream); string articleContent = sr.ReadToEnd(); List<CnblogsModel> list = new List<CnblogsModel>(); #region 正則表達式 //文章內容 Regex regContent = new Regex(@"<div\sid=""cnblogs_post_body""[^>]*?>(.*?)</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); #endregion MatchCollection mList = regContent.Matches(articleContent); var returncontent = ""; if (mList.Count > 0) returncontent = mList[0].Groups[0].ToString(); return returncontent; } #endregion #region 指定鏈接採集 //指定鏈接採集 public static List<CnblogsModel> GetUrl(string URL) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); request.Method = "GET"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.UserAgent = " Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream stream = response.GetResponseStream(); StreamReader sr = new StreamReader(stream); string articleContent = sr.ReadToEnd(); List<CnblogsModel> list = new List<CnblogsModel>(); #region 正則表達式 //文章標題 Regex regTitle = new Regex(@"<a\sid=""cb_post_title_url""[^>]*?>(.*?)</a>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); //文章內容 Regex regContent = new Regex(@"<div\sid=""cnblogs_post_body""[^>]*?>(.*?)</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); #endregion MatchCollection mList = regTitle.Matches(articleContent); MatchCollection mList2 = regContent.Matches(articleContent); CnblogsModel model = new CnblogsModel(); //文章標題 model.ArticleTitle = mList[0].Groups[0].ToString(); model.ArticleContent = mList2[0].Groups[0].ToString(); list.Add(model); return list; } #endregion //實體 public class CnblogsModel { /// <summary> /// 文章鏈接 /// </summary> public String ArticleUrl { get; set; } /// <summary> /// 文章標題(帶鏈接) /// </summary> public String ArticleTitle { get; set; } /// <summary> /// 文章標題(不帶鏈接) /// </summary> public String ArticleTitle2 { get; set; } /// <summary> /// 文章內容摘要 /// </summary> public String ArticleContent { get; set; } /// <summary> /// 文章作者 /// </summary> public String ArticleAutor { get; set; } /// <summary> /// 文章發佈時間 /// </summary> public String ArticleTime { get; set; } /// <summary> /// 文章評論量 /// </summary> public Int32 ArticleComment { get; set; } /// <summary> /// 文章瀏覽量 /// </summary> public Int32 ArticleView { get; set; } } #endregion } }
源碼下載
鏈接://pan.baidu.com/s/10lDUZju3FAmFFTrVrWqg3Q
提取碼:xion
寫在後面
朋友們看到這裡是不是發現除了分析數據結構和寫正則表達式比較費勁,其他的就是一些常規操作?
沒錯,只要你會分析數據結構和數據解析,那麼任何數據對你來說都是信手拈來;
參考:百度百科://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB/5162711?fr=aladdin。
![]() 歡迎關注訂閱我的微信公眾平台【熊澤有話說】,更多好玩易學知識等你來取
作者:熊澤-學習中的苦與樂 公眾號:熊澤有話說 出處: //www.cnblogs.com/xiongze520/p/14177274.html 創作不易,版權歸作者和博客園共有,轉載或者部分轉載、摘錄,請在文章明顯位置註明作者和原文鏈接。
|