c# 爬蟲(二) 模擬登錄


有了上一篇的介紹,這次我們來說說模擬登錄,上一篇見 :c# 爬蟲(一) HELLO WORLD

原理

我們知道,一般需要登錄的網站,服務器和客戶端都會有一段時間的會話保持,而這個會話保持是在登錄時候建立的, 服務端和客戶端都會持有這個KEY,在后續訪問時,都需要核對這兩個KEY是否一致。 而客戶端的這個KEY就存在cookie中。 因此,我們需要獲取登錄后的cookie值,並在后續的訪問中,都添加這個cookie。這樣才能做到模擬登錄的效果。

 

例子:

我們以獲取博客園首頁的園齡為例。需要做三步

1. 模擬登錄博客園

2. 構建個人主頁的Request請求,包括cookie

3. 獲取個人主頁的數據后, 分析頁面,並獲取園齡的數據。

代碼如下:

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;
        }

 

注意事項

 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM