最近在爬一個叫做"雅學資訊網(wǎng)"的網(wǎng)站的時候膊升,在翻頁的時候發(fā)現(xiàn)翻不動绿渣,做翻頁請求時會報錯非春。仔細查了以下發(fā)現(xiàn)跟ViewState和EVENTVALIDATION兩個東西有關。(兩個值的具體用法我寫在最后,如果光為了解決爬蟲問題可能不需要對這兩個值有太深的理解溯职,所以我先寫下爬蟲應該如何應對)
一、應對方法
在頁面上我們可以找到這么一段div,其中value的值便是當前頁面的ViewState
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTEyODcxMjQ1NjAPZBYCAgMPZBYEAgYPFgIeBFRleHQF9AM8dHI+PHRkIGhlaWdodD0iMTkiIGNsYXNzPSJ0ZXh0MSI+wrc8YSBocmVmPSJodG1sL3NjZGx1bi5odG1sIiB0YXJnZXQ9Il9ibGFuayI+U0NE5rqQ5pyf5YiK6K665paH6K6h566X5qCH5YeGPC9hPjwvdGQ+PHRkIGhlaWdodD0iMTkiIGNsYXNzPSJ0ZXh0MSI+wrc8YSBocmVmPSJodG1sL3NjZGNobi5odG1sIiB0YXJnZXQ9Il9ibGFuayI+U0NE5Lit5paH5rqQ5pyf5YiK562b6YCJ6L+H56iLPC9hPjwvdGQ+PC90cj48dHI+PHRkIGhlaWdodD0iMTkiIGNsYXNzPSJ0ZXh0MSI+wrc8YSBocmVmPSJodG1sL3NjaXNjZGx1bi5odG1sIiB0YXJnZXQ9Il9ibGFuayI+MjAwNH4yMDA55bm0U0NJ44CBU0NE5a2m56eR6Zeo6K665paH5pWwDQo8L2E+PC90ZD48dGQgaGVpZ2h0PSIxOSIgY2xhc3M9InRleHQxIj7CtzxhIGhyZWY9Imh0bWxcc2Npc2NkLmh0bWwiIHRhcmdldD0iX2JsYW5rIj4yMDA0fjIwMDnlubRTQ0njgIFTQ0TkuIDnuqflrabnp5HorrrmlofmlbA8L2E+PC90ZD48L3RyPmQCCg9kFgICAQ8WAh8ABQ8xMjIuMjM1LjIyNy4yMTBkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYCBQhidG5Mb2dpbgUIYnRuUmVzZXRtFvhkMyHYuQBS5+NctLObmaPtUA==" />
</div>
下面這一段是EVENTVALIDATION的
<div>
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="90059987" />
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBQLii7WQCAKl1bKzCQK1qbSRCwKC3IeGDAKgt7D9Cq786rV3YQHSWN8A2IZl0Z5gnwxM" />
</div>
簡單來說我們把這個頁面的html解析獲取這兩個值醒第,然后在執(zhí)行post請求時加到PostData屬性里就可以了。
但是
在翻頁的時候可能還會有一個坑进鸠,我們有時會需要子頁面中的內容稠曼。這個時候子頁面爬取的順序就有點講究了。
正確順序在第三部分客年,不需要看我踩坑過程的直接看第三部分蒲列。
1、流水賬順序(坑)
如果我們按照下圖這樣的順序搀罢,會發(fā)現(xiàn)我們在第一頁子頁c跳轉到第二頁的時候會失敗蝗岖。
-
1、 使用子頁C的ViewState和EVENTVALIDATION進行請求
翻頁這個指令要從第一頁發(fā)出榔至,所以需要第一頁的屬性進行請求抵赢。 -
2、在子頁面直接使用第一頁的ViewState和EVENTVALIDATION的進行請求
屬性和頁面一定要對應唧取,也就是“子頁C用第一頁的屬性”這種操作是不可行的铅鲤。
2、改良流水賬順序(坑)
我們由上面知道了一定要第一頁才能跳轉第二頁枫弟,那我們每次訪問完子頁面都返回一下可不可以呢邢享?
答案是不可以
其實我們的第一頁是搜索請求的來的,或者GET訪問得來的淡诗,那第一頁子頁C跳轉第一頁還是可以實現(xiàn)的骇塘。但是到了第二頁子頁C跳轉第二頁的時候,我們就又跳不動了韩容,我們需要第一頁才能跳第二頁款违。
-
當然你們一定不會想用這樣的順序吧哈哈(不過可能某些特殊情況真的需要這種..)。
3群凶、先所有父頁再所有子頁(成功)
按照本身應該的一頁跳二頁插爹,二頁跳三頁的順序爬取(先不管子頁面),再爬每一頁時存儲好該頁的Html或者跳轉子頁面的信息,先把所有父頁面爬好赠尾,再根據(jù)本地的信息爬所有子頁面力穗。
二、ViewState和EVENTVALIDATION的原理
1气嫁、ViewState
當請求某個頁面時当窗,ASP.NET把所有控件的狀態(tài)序列化成一個字符串,然后做為窗體的隱藏屬性送到客戶端杉编。當客戶端把頁面回傳時超全,ASP.NET分析回傳的窗體屬性,并賦給控件對應的值邓馒。
2嘶朱、EVENTVALIDATION
“id”屬性為“__EVENTVALIDATION”的隱藏字段是ASP.NET 2.0的新增的安全措施。該功能可以阻止由潛在的惡意用戶從瀏覽器端發(fā)送的未經(jīng)授權的請求.
為了確保每個回發(fā)和回調事件來自于所期望的用戶界面元素光酣,ASP.NET運行庫將在事件中添加額外的驗證層疏遏。服務器端通過檢驗表單提交請求的內容,將其與“id”屬性為“__EVENTVALIDATION”隱藏字段中的信息進行匹配救军。根據(jù)匹配結果來驗證未在瀏覽器端添加額外的輸入字段(有可能為用戶在瀏覽器端惡意添加的字段)财异,并且該值是在服務器已知的列表中選擇的。ASP.NET運行庫將在生成期間創(chuàng)建事件驗證字段唱遭,而這是最不可能獲取該信息的時刻戳寸。像視圖狀態(tài)一樣,事件驗證字段包含散列值以防止發(fā)生瀏覽器端篡改拷泽。