最近公司需要開發一個簡曆匯入功能,類似部落格搬家或者郵箱搬家,之前抓取資訊是利用火車採集器,但是簡曆匯入功能需要使用者登陸以後才能擷取簡曆資料,無奈只好自己開發了。
首先是遇到的問題是:如何?類比登陸?
我們知道一般的網站都是通過Cookies來維護狀態的,我抓的網站也是支援利用Cookies來驗證使用者的,構造一個post資料包,向伺服器提交資料,在配置火車採集器的時候,也是要先利用WSockExpert.exe工具獲得Post資料包,之後修改使用者名稱和密碼,向伺服器提交的。
提交了登陸資料後還沒完成登陸,雖然伺服器會返回登陸後的頁面資料,但是如果在進入其他的連結頁面,還是不允許的,因為伺服器每次都需要通過你提交過去Cookies來驗證你是否登陸,在asp.net裡,利用Cookies儲存身分識別驗證票證,每次都需要向伺服器提交的,初學asp.net總是弄不明它的form驗證機制,它封裝了太多資訊,雖然用幾行代碼就能實現驗證,後來看了些web開發基礎知識才弄明白,在這個你需要儲存上次登陸後返回的Cookies,在下次有其他請求時帶上這個Cookies就可以了,怎麼帶上呢?下面是我在.net裡的實現,很簡單!
利用HttpWebRequest類的CookieContainer來儲存,這個CookieContainer會儲存伺服器回傳的Cookies,但是前提是你在初始化HttpWebRequest的時候,記得執行個體化這個CookieContainer,一般的請求不需要執行個體它的,簡單的代碼如下:
httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
httpWebRequest.CookieContainer = new CookieContainer();
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST"
為了能全域使用這個CookieContainer ,你可以把它作為全域變數,這樣在下次request的時候將其賦給CookieContainer 屬性就行了。
詳細瞭解CookieContainer 見:http://msdn.microsoft.com/zh-cn/vstudio/system.net.cookiecontainer(VS.80).aspx
維護了這個CookieContainer 後,我們就可以訪問登陸後的頁面了,類比登陸問題解決。
其次遇到的問題自然是:如果從網頁上獲得想要的資訊?
要在網頁抓取資訊,實現起來最簡單,同時也是最繁瑣的方法,那就是模板方法擷取了,從火車採集器的配置過程看出來,它也就是用這種方法而已,不過人家能把抓取器做成成熟的產品,並且熱賣,這個比不了,所以成功與否不完全取決於技術,火車採集器雖然配置起來挺繁瑣,但是用起來還不錯。
用這種方式你需要做個一個模板,你需要知道目標網頁的結構,知道要找的資訊在什麼地方,之後記錄在它的前面和後面的字串,你可以利用截取字串的方式獲得目標資訊,也可以利用正則標式獲得,要保證前面和後面的字串是唯一的,很簡單,計算一下,或者匹配一下就可以獲得目標資訊,但是實際做起來還是會遇到一些問題:
下面是我遇到問題;
1.首先我是想利用Regex匹配,但是模組裡設定的首碼和尾碼裡有斷行符號換行/r/n,結果總是匹配不成功,我正則的功底很差,最後知道怎麼回事了,把/r/n替換成(/s*),問題解決,您可以想出為什麼了吧?
2.利用字串截取方式擷取,在正則還不是很精通,用這種方式最保險了,但是在截取字串前記得調整下目標頁代碼,從xml設定檔裡讀取的首碼和尾碼中可能有斷行符號和換行,但是斷行符號換行在不同系統裡字元表現是不一樣的,Windows裡是/r/n,Linux裡是/n,所以要記得統一。
3.前尾碼不唯一,有時在頁面裡有兩個不同的目標資訊,但卻有相同的首碼,比如:
<td width="25%" class="ResTbLfPd">資料庫</td>
<td width="25%" class="ResTbLfPd">軟體工程師</td>
如果用相同的首碼就比較難截到想要的資訊了,我想了個辦法,當然方法可能比較笨,但是問題解決了,也是火車給我的啟示,利用多個字串定位目標資訊,比如我想抓去 軟體工程師 ,首碼就是:
<td width="25%" class="ResTbLfPd">*</td>
<td width="25%" class="ResTbLfPd">
在資訊可能不同的地方用*代替,類似萬用字元,這樣利用*將一個字串切割為兩個,先找到第一個,之後以這個索引位置為起點,再找第二個字串,這樣就可以定位到最終的資訊了,同樣可以用多個字串三個或更多,這樣實現是解決了問題,希望有更好的方式,希望以後會改進。
4.在抓取資訊的時候還可以利用MITHtmlPparser,這是一個開源的類庫,在codeproject找搜到的,將網頁內的所以標籤都分析出來,如果擷取資訊不是很多、很碎的話,用這個也比較好用,只需知道那個最終要得到資訊在那個標籤裡,然後直接取出就行了。
好了,希望在新的一年裡能學到更多,能經得住考驗!