相信所有個人網(wǎng)站的站長都有抓取別人數(shù)據(jù)的經(jīng)歷吧,,目前抓取別人網(wǎng)站數(shù)據(jù)的方式無非兩種方式: 一,、使用第三方工具,其中最著名的是火車頭采集器,,在此不做介紹,。
二、自己寫程序抓取,,這種方式要求站長自己寫程序,,可能對對站長的開發(fā)能力有所要求了。
本人起初也曾試著用第三方的工具抓取我所需要的數(shù)據(jù),,由于網(wǎng)上的流行的第三方工具不是不符合我的要求,,就是過于復(fù)雜,我一時沒有搞明白怎么用,,后來索性決定自己寫吧,,現(xiàn)在本人基本上半天可以搞定一個網(wǎng)站(只是程序開發(fā)時間,不包括數(shù)據(jù)抓取的時間),。 經(jīng)過一段時間的數(shù)據(jù)抓取生涯,也曾遇到了很多困難,,其中最常見的一個就是關(guān)于分頁數(shù)據(jù)的抓取問題,,原因在于分?jǐn)?shù)據(jù)分頁的形式有很多種,下面我主要針對三種 形式介紹一下抓取分頁數(shù)據(jù)的方法,,此類文章雖然在網(wǎng)上見過很多,,但每次拿別人的代碼總也總是有各種各樣的問題,下面各種方式的代碼都是能正確執(zhí)行,,并且我 目前也正在使用中的,。本文中代碼實現(xiàn)是用C#語言來實現(xiàn)的,我想其他語言原理大致相同,。 下面切入正題:
第一種方式:URL地址中包含分頁信息,,這種形式是最簡單的,這種形式使用第三方工具抓取也很簡單,,基本上不用寫代碼,,對于我這種寧可自己花個半天時間寫代碼也懶得學(xué)第三方工具的人,還是通過自己寫代碼實現(xiàn)了,; 這種方式就是通過循環(huán)生成數(shù)據(jù)分頁的URL地址 如: 這樣通過HttpWebRequest訪問對應(yīng)URL地址,,返回對應(yīng)頁面的html文本,接下來的任務(wù)就是對字符串的解析,,將需要的內(nèi)容保存到本地數(shù)據(jù)庫內(nèi),;抓取的代碼可參考下面:
public string GetResponseString(string url){
上面的代碼可以返回對應(yīng)頁面的html內(nèi)容的字符串,剩下的工作就是從這個字符串中獲取自己關(guān)心的信息了,。
第二種方式:可能 是通過asp.net開發(fā)的網(wǎng)站常會遇到,,它的分頁控件通過post方式 提交分頁信息到后臺代碼,,如.net下Gridview自帶的分頁功能,當(dāng)你點擊分頁的頁碼時,,會發(fā)現(xiàn)URL地址沒有變化,,但頁碼變化了,頁面內(nèi)容也變 化,,仔細(xì)看會發(fā)現(xiàn),,把鼠標(biāo)移到每個頁碼上的時候狀態(tài)欄會顯示 javascript:__dopostback("gridview","page1")等等 之類的代碼,這種形式其實也不是很難,,因為畢竟有地方得到頁碼的規(guī)律可尋,。
我們知道http請求提交的方式有兩種一種是get一種是Post,第一種方式是get方式,,那么第二種方式就是post方式,,具體提交的原理不必細(xì)說,不是本文的重點
抓取這種頁面 需要注意asp.net頁面的幾個重要的元素
一,、 __VIEWSTATE ,,這個應(yīng)該是.net特有的,也是讓.net開發(fā)人員既愛又恨的東西,,當(dāng)你打開一個網(wǎng)站的某一個頁面的時候,,如果發(fā)現(xiàn)這個東西,而且后面還跟隨著一大堆亂七八糟的字符的時候,,那這個網(wǎng)站肯定是用asp.net寫的了;
二,、__dopostback方法,這個是asp.net頁面自動生成一個javascript方法,,包含兩個參 數(shù),,__EVENTTARGET,__EVENTARGUMENT,,這兩個參數(shù)可以參看頁碼對應(yīng)的內(nèi)容,,因為點擊翻頁的時候,會將頁碼信息傳給這兩個參 數(shù),。
三,、__EVENTVALIDATION 這個也也應(yīng)該是asp.net特有的東西
大家也不用 太關(guān)心這三個東西都是干什么的,只需要注意自己寫代碼抓取頁面的時候 記得提交這三個元素就可以了,。
和第一種方式一樣,,肯定要通過循環(huán)的方式是去拼湊_dopostback的兩個參數(shù),只需要拼其中包含了頁碼信息的參數(shù)即可,。這里有一個需要注意的地方,, 就是在每次通過Post提交請求下一頁的時候,先應(yīng)得到當(dāng)前頁的__VIEWSTATE 信息和__EVENTVALIDATION信息,所以分頁數(shù)據(jù)的第一頁可采用第一種方式得到頁碼內(nèi)容然后,,同時取出對應(yīng)的__VIEWSTATE 信息和__EVENTVALIDATION信息,,然后再做循環(huán)處理下一頁面,然后每抓取完一個頁面,,再記錄下__VIEWSTATE 信息和__EVENTVALIDATION信息,,為下一個頁面post提交數(shù)據(jù)使用
參考代碼如下:
for (int i = 0; i < 1000; i++){
正所謂外行看熱鬧,內(nèi)行看門道,,很多人可能看到這里就會說用Webbrowser這可控件就可以實現(xiàn),,對,我下面的這種方式就是用WebBrowser的 這個控件來實現(xiàn),,其實在.net下這種類似的類應(yīng)該還有,但我沒有去研究過,,也希望如果有人有其他的方式,,可以回復(fù)我,與大家一起分享,。
WebBroser控件可是在自己的程序中內(nèi)嵌一個瀏覽器,,就像IE,火狐之類的一樣,,你也可以用他開發(fā)自己的瀏覽器,,至于用它開發(fā)的瀏覽器的效果怎么樣,我覺得肯定是不如IE和火狐了,。呵呵
我們還是 閑言少敘,,切入主題:
使用WebBroser控件基本上可以實現(xiàn)你在IE中操作網(wǎng)頁的任何功能,所以點擊翻頁按鈕當(dāng)然也是可以的了,,那既然可以在WebBroser中可以手動點擊翻頁按鈕,,自然我們用程序代碼同樣可以指使WebBroser自動替我們翻頁了。
其實原理很簡單,主要分以下幾個步驟:
第一步,,打開你想抓取的頁面 比如:http://www./zr/list_O.html
調(diào)用webBrowser控件的方法Navigate("http://www./zr/list_O.html");
此時,,你應(yīng)該在你的WebBrowser控件中看到你的網(wǎng)頁信息,和IE中看到的是一樣的,;
第二步 ,,WebBrowser控件的這個事件DocumentCompleted 很重要,當(dāng)你訪問的頁面全部加載完之后,,會觸發(fā)這個事件,。所以我們分析頁面元素的過程也需要在這個事件內(nèi)完成
string _ResponseStr=this.WebBrowser1.Document.Body.OuterHtml;
這句代碼可以得到當(dāng)前打開頁面的html元素的內(nèi)容。
既然已經(jīng)得到當(dāng)前打開頁面的html元素的內(nèi)容了,,剩下的工作自然就是解析這個大字符串,,得到自己關(guān)心的內(nèi)容,解析字符串的過程,,大家應(yīng)該自己都能寫了,。
第三步, 重點在這第三步呢,,因為要翻頁了,,接第二步,解析完字符串之后,,還是在DocumentCompleted事件中,,調(diào)用方法
WebBrowser1.Document.GetElementById("頁碼的id").InvokeMember("click");
從代碼的方法名種大家應(yīng)該能明白了,那么調(diào)用完這個方法,,之后WebBrwoser控件內(nèi)的網(wǎng)頁就實現(xiàn)了翻頁,,和你用手去點翻頁按鈕是一樣的效果。
重點在于,,翻頁之后,,還會觸發(fā)DocumentCompleted事件,所以進(jìn)入了第二步,,第三步的循環(huán)了,,所以大家需要注意判斷跳出循環(huán)的時機(jī)。 其實用WebBrowser還能干很多事情,,比如自動登錄,,注銷某個論壇,保存session,, cockie,,所以 這個控件基本上可以實現(xiàn)你想對網(wǎng)頁的任何操作,哪怕你是想暴利破解一個網(wǎng)站的登錄密碼,,當(dāng)然這個是不提倡的了,。呵呵 |
|
來自: LibraryPKU > 《Web》