.net 信息採集ajax數據 關於.net信息採集的資料很多,但是如果採集的網站是ajax非同步載入數據的模式,又如何採集呢?今天就把自己做信息採集時,所遇到的一些問題和心得跟大家分享一下。 採集網站的幾種方式與利弊: 利用系統自帶HttpWebRequest對象,採集網站內容,優點是採集效率快,但 ...
.net 信息採集ajax數據
關於.net信息採集的資料很多,但是如果採集的網站是ajax非同步載入數據的模式,又如何採集呢?今天就把自己做信息採集時,所遇到的一些問題和心得跟大家分享一下。
採集網站的幾種方式與利弊:
- HttpWebRequest
利用系統自帶HttpWebRequest對象,採集網站內容,優點是採集效率快,但是如果網站是ajax非同步載入數據的方式,是採集不到網頁內容的,並且網站沒有採用ajax的方式,在網頁中用到了javascript,比如說:網頁內容用document.write的方式輸出到網頁中的,這種情況也是獲取不到內容的。其次還需要知道對方網站的編碼格式(就是網頁頭部中<meta charset="utf-8"/>),如果採集時網站編碼格式錯誤的話,會導致採集的內容是亂碼。但這個是小問題,我自己當時查閱資料時找到了別人封裝好的方法,但是很慚愧因為不知道作者是誰了,我會把相應的代碼下載鏈接提供給大家。以上的問題是因為js和ajax是需要瀏覽器去解析的,所以導致了獲取不到網頁內容。
Help.HttpHelp.HttpRequest("採集的網址");
2.瀏覽器控制項
因為當時我開發的時候,用的是cs模式,相信大家同樣也會用cs的模式去開發這個功能。既然是cs模式(不考慮美觀)的情況下肯定是WinForm,WinForm中有自帶的瀏覽器控制項,這個是不好用的,我當時用的是Geckofx,基於火狐內核的一款瀏覽器控制項,但是這方面的資料很少,當時遇到了一些問題都找不到解決方法,但後來還是都解決了。用了該控制項就可以獲取到ajax非同步載入的數據,在網頁載入完成之後,延遲幾秒鐘獲取網頁內容,就可以很方便的獲取到網頁內容,缺點是相對第一種方案來說的話會慢一些,因為它是一個瀏覽器控制項,需要渲染html和解析js等操作。
GeckoWebBrowser webBrowser = null; private void Form1_Load(object sender, EventArgs e) { string xulrunnerPath = AppDomain.CurrentDomain.BaseDirectory + "\\bin"; Xpcom.Initialize(xulrunnerPath); //設置為3阻止所有的彈出視窗, GeckoPreferences.User["privacy.popups.disable_from_plugins"] = 3; //禁止載入圖片 GeckoPreferences.User["permissions.default.image"] = 2; webBrowser = new GeckoWebBrowser(); webBrowser.Navigate("http://www.baidu.com"); webBrowser.DocumentCompleted += DocumentCompleted; } private void DocumentCompleted(object sender, Gecko.Events.GeckoDocumentCompletedEventArgs e) { var time = new System.Windows.Forms.Timer(); time.Interval = 2000; time.Tick += (a, b) => { time.Stop(); string html = ""; //頁載入完成 GeckoHtmlElement element = null; var geckoDomElement = webBrowser.Document.DocumentElement; if (geckoDomElement != null && geckoDomElement is GeckoHtmlElement) { element = (GeckoHtmlElement)geckoDomElement; //網頁內容 html = element.InnerHtml; txtHtml.Text = html;
/*
//通過xpath 查找class為btnLogin的元素
GeckoNode btnLogin = webBrowser.Document.SelectFirst(".//*[@class='btnLogin']");
if (btnLogin != null)
{
GeckoHtmlElement ie = btnLogin as GeckoHtmlElement;
//手動觸發點擊事件
ie.Click();
}*/ } }; time.Start(); }
3.phantomjs
phantomjs可以把它理解為也是一個瀏覽器控制項,只不過它使用QtWebKit作為它核心瀏覽器的功能,使用webkit來編譯解釋執行JavaScript代碼。利用該組件就可以很方便的獲取到網頁內容,同時也包括了ajax載入的數據,如果是分頁的情況下,首次載入不需要延遲,如果獲取第2頁及以上內容的話同樣也需要延遲才能獲取到,並且它可以很方便的完成網頁快照(就是網頁截屏),至於其他的功能大家可以自己查閱一下資料。
IWebDriver driver = null; private void btnGo_Click(object sender, EventArgs e) { string phantomjsDire = AppDomain.CurrentDomain.BaseDirectory; PhantomJSDriverService service = PhantomJSDriverService.CreateDefaultService(phantomjsDire); service.IgnoreSslErrors = true; service.LoadImages = false; service.ProxyType = "none"; driver = new PhantomJSDriver(phantomjsDire); /*IWindow iWindow = driver.Manage().Window; iWindow.Size = new Size(10,10); iWindow.Position = new Point(0, 600);*/ driver.Navigate().GoToUrl(textBox1.Text); string html = driver.PageSource; txtHtml.Text = html; //driver.Close(); //driver.Quit(); } private void btnPage_Click(object sender, EventArgs e) { // .//*[@class='next'][text()='下一頁'] // .//*[@class='text'] // .//*[@class='button'] //IWebElement element = driver.FindElement(By.XPath(".//*[@class='text']")); //給網頁中文本框賦值 //element.SendKeys("4"); IWebElement btnElement = driver.FindElement(By.XPath(".//*[@class='next'][text()='下一頁']")); btnElement.Click(); var time = new System.Windows.Forms.Timer(); time.Interval = 2 * 1000; time.Tick += (a, b) => { time.Stop(); string html = driver.PageSource; txtHtml.Text = html; }; time.Start(); }
網站內容中url地址如果是相對地址的話,就是../../a.html,這種情況要想獲取絕對地址的話,可以用以下方法:
/// <summary> /// 獲取絕對url地址 /// </summary> /// <param name="baseUri">當前頁地址</param> /// <param name="relativeUri">相對路徑地址</param> /// <returns></returns> public static string GetRealUrl(string baseUri, string relativeUri) { try { baseUri = System.Web.HttpUtility.UrlDecode(baseUri); relativeUri = System.Web.HttpUtility.UrlDecode(relativeUri); Uri baseUriModel = new Uri(baseUri); Uri uri = new Uri(baseUriModel, relativeUri); string result = uri.ToString(); baseUriModel = null; uri = null; return result; } catch (Exception ex) { } return relativeUri; }
總結:
以上說的第2、3種方式都可以獲取到ajax非同步載入的內容,同時還能通過xpath模式查找網頁中的元素,例如分頁標簽和按鈕,找到元素之後可以調用click點擊事件,就能輕鬆的解決分頁問題。好多網站分頁分到最後一頁的時候,處理的情況都不一樣,需要自己去處理,例如有的隱藏下一頁按鈕、有的是禁用等等。
獲取到網頁內容之後,要想獲取自己需要的內容,可以通過HtmlAgilityPack插件,它是通過xpath的模式查找內容。
以下我會將自己開發的信息採集系統截圖發出來。
歡迎任何形式的轉載,但請務必註明出處。
文案功底有限,碼字不易,不喜勿噴,如果文章和代碼有表述不當之處,還請不吝賜教。