c# 爬蟲(二) 模擬登陸

有了上一篇的介紹,此次咱們來講說模擬登陸,上一篇見 :c# 爬蟲(一) HELLO WORLDhtml

原理web

咱們知道,通常須要登陸的網站,服務器和客戶端都會有一段時間的會話保持,而這個會話保持是在登陸時候創建的, 服務端和客戶端都會持有這個KEY,在後續訪問時,都須要覈對這兩個KEY是否一致。 而客戶端的這個KEY就存在cookie中。 所以,咱們須要獲取登陸後的cookie值,並在後續的訪問中,都添加這個cookie。這樣才能作到模擬登陸的效果。chrome

 

例子:c#

咱們以獲取博客園首頁的園齡爲例。須要作三步服務器

1. 模擬登陸博客園cookie

2. 構建我的主頁的Request請求,包括cookiesession

3. 獲取我的主頁的數據後, 分析頁面,並獲取園齡的數據。app

代碼以下:工具

static void Main(string[] args)
        {
            //string html= Hello();
            string html = LoginSimulation();
            Console.WriteLine(html);
            Console.Read();
        }
 static string LoginSimulation()
        {
            
            string url = "https://passport.cnblogs.com/user/signin";
            string postData = "{\"input1\":\"MvxmwEWfUF26IvKNa1dUiZn1xmSBhNW0wJyoaUlDPXoh+Mb+z2eZK3r3c9Jd0aT0/Wzz3ht7LMeTllu8ISY9nfQIuKB0C19Y9/IfKYSktpZZOVaKx/XP3i/mGxXC3K5m2la91ViRh3BO36xT4E98dbqVHPtynjuNafuVIBF5a2M=\",\"input2\":\"xxxx":false}";

            //1.獲取登陸Cookie
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";// POST OR GET, 若是是GET, 則沒有第二步傳參,直接第三步,獲取服務端返回的數據
            req.AllowAutoRedirect = false;//服務端重定向。通常設置false
            req.ContentType = "application/x-www-form-urlencoded";//數據通常設置這個值,除非是文件上傳

            byte[] postBytes = Encoding.UTF8.GetBytes(postData);
            req.ContentLength = postBytes.Length;
            Stream postDataStream = req.GetRequestStream();
            postDataStream.Write(postBytes, 0, postBytes.Length);
            postDataStream.Close();

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            string cookies = resp.Headers.Get("Set-Cookie");//獲取登陸後的cookie值。

            //2.登陸想爬取頁面的構造,主要多一個Cookie的構造
            string contentUrl = "https://home.cnblogs.com/u/xinjian/";
            HttpWebRequest reqContent = (HttpWebRequest)WebRequest.Create(contentUrl);
            reqContent.Method = "GET";
            reqContent.AllowAutoRedirect = false;//服務端重定向。通常設置false
            reqContent.ContentType = "application/x-www-form-urlencoded";//數據通常設置這個值,除非是文件上傳

            reqContent.CookieContainer = new CookieContainer();
            reqContent.CookieContainer.SetCookies(reqContent.RequestUri, cookies);//將登陸的cookie值賦予這次的請求。

            HttpWebResponse respContent = (HttpWebResponse)reqContent.GetResponse();
            string html = new StreamReader(respContent.GetResponseStream()).ReadToEnd();

            //3. 分析讀取該頁面的數據,可使用HtmlAgilityPack第三方類,這裏比較簡單,本身寫個獲取方法就行
            string age= GetVal(html, "<span title='入園時間:2010-6-28'>", "</span>");
            return age;
        }

 

注意事項post

 1. 本次模擬登陸,我發現chrome的開發人員工具,並無抓到真正的Post包,和我以前遇到的狀況同樣, 後來仍是使用了httpwatch後,才抓到了真正的數據包。博客園作的不錯,提交的數據進行了加密。 固然個人密碼我也已經改爲了XXX,用戶須要運行的話,須要自行抓包獲取對應的postData。

 

2. 針對cookie的賦值,主要由這兩句完成

            reqContent.CookieContainer = new CookieContainer();
            reqContent.CookieContainer.SetCookies(reqContent.RequestUri, cookies);//將登陸的cookie值賦予這次的請求。

可是據說C#封裝的不是很好,有時候會漏掉數據,但我目前還沒遇到過, 若是遇到,須要將cookie的string手工轉換成CookieCollection,並賦予CookieContainer。

 

3. 針對ASP.NET的網頁, 會存在__VIEWSTATE & __EVENTVALIDATION 這兩個post字段, 對於沒創建會話時,這兩個值是不會變的,而一旦創建會話(模擬登錄後),每次訪問的頁面,這兩個值都會改變, 解決辦法是先使用GET獲取該頁面的數據後,獲取這兩個字段的值, 而後在post的時候,進行賦值。 

 

4. 在遇到500錯誤的時候,說實話,我也很頭疼,不知道如何調試,但我總結下來,必定是request構建的不對。主要查看以下問題:

  4.1. 對比post的數據的key和value,看看格式是否正確,如是否進行了編碼 WebUtility.UrlEncode()。 

  4.2. 對比post的數據的,是否Post了所有的數據, 固然這裏不光是當前頁面,有時候還會用到其餘頁面,我舉個例子, 我在訂單頁面上傳附件, 在附件上傳頁面,發現並無Post訂單的id,那麼這個時候,就須要查找訂單的id服務端是何時獲取的,這個時候就須要猜了,有多是在打開訂單頁面的時候,服務端就把此id存儲到session中了。因此先須要模擬打開訂單頁面,而後在模擬訂單附件上傳的post。

  4.3 注意是是否犯了__VIEWSTATE & __EVENTVALIDATION的錯誤,注意,針對數據型的post,須要進行urlEncode。

  4.4 Request的Head是否構建全了, 有時候客戶端會提交自定義的head,注意查看。同時UserAgent有時候也會須要進行變化,但目前我還沒遇到過。

  4.5. 若是肯定Post的數據全了,而且仍是500錯誤的話,考慮下是否cookie有問題,雖然我還沒遇到過。

 

目前就想到這麼多,模擬登陸當時我也卡了兩天,主要當時對__VIEWSTATE & __EVENTVALIDATION的理解仍是不夠,後續若是有疑問的話,我會專門開一篇ASP.NET的模擬登陸。

參考文獻:

http://www.crifan.com/emulate_login_website_using_csharp/

http://www.cnblogs.com/zuoguanglin/archive/2012/03/28/2421153.html

https://msdn.microsoft.com/en-us/library/ms972976.aspx

相關文章
相關標籤/搜索