年輕人不講武德
相信很多朋友都有這種苦惱:自己的文章被搬運了!
你上午在部落格園、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=""likecs_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("https://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=""likecs_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=""likecs_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
}
}
源碼下載下傳
連結:https://pan.baidu.com/s/10lDUZju3FAmFFTrVrWqg3Q
提取碼:xion
寫在後面
朋友們看到這裡是不是發現除了分析資料結構和寫正規表達式比較費勁,其他的就是一些正常操作?
沒錯,隻要你會分析資料結構和資料解析,那麼任何資料對你來說都是信手拈來;
參考:百度百科:https://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB/5162711?fr=aladdin。
歡迎關注訂閱我的微信公衆平台【熊澤有話說】,更多好玩易學知識等你來取 作者:熊澤-學習中的苦與樂 公衆号:熊澤有話說 出處: https://www.cnblogs.com/xiongze520/p/14177274.html 創作不易,版權歸作者和部落格園共有,轉載或者部分轉載、摘錄,請在文章明顯位置注明作者和原文連結。 |