1. 程式人生 > >C#使用webclient獲取搜房html內容的亂碼問題

C#使用webclient獲取搜房html內容的亂碼問題

這幾天使用c#的webclient進行網站頁面內容的獲取,但是在獲取搜狐網頁內容時,總是亂碼。開始以為是編碼的問題,但是不管使用gb2312、gbk、utf8,最終的結果都是亂碼,程式碼如下:
                        WebClient wc = new WebClient();
                          byte[] pageData = web.DownloadData(url);
                        string strWeb = Encoding.Default.GetStringGetString(pageData );
        最後發現是因為搜房網站頁面進行了壓縮導致,為便於學習與儲存,以下內容摘抄自

擴充套件WebClient支援gzip,deflate壓縮頁面的自解壓,解決亂碼問題頁面內容:

       為了加快頁面的下載速度,提升WEB伺服器的效能,現在的很多網站,都開啟了頁面的壓縮輸出功能,常用的 gzip 和 deflate 。 

        在 .NET 平臺上,做網頁採集,常用的方式是使用 HttpWebRequest 和 WebClient。

        HttpWebRequest 是對 WebRequest 的http協議的實現。而WebClient是對HttpWebRequest的一個輕量級的封裝。

        HttpWebRequest 功能完備,強大,但是使用較繁瑣,相比之下,WebClient 就簡單易用多了,但是,這個簡單也是必定有代價的,那就是精簡了很多HttpWebRequest具備的功能,例如:WebClient對Cookie的支援就被砍掉了。 

        從 .NET 2.0 開始,WebRequest就具備了對壓縮網頁自解壓的功能。實現的程式碼,大致如下:  

        HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);

        hwr.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;

         很明顯,就是 AutomaticDecompression 這個屬性的使用,但是這個屬性的預設值是 DecompressionMethods.None 。

        正是這個功能,在 WebClient 的實現裡,也被精簡掉了,導致 WebClient 繼承來的 WebRequest 的 AutomaticDecompression 屬性不能被更改。

        從而出現了,使用WebClient獲取被壓縮的頁面時,雖然指定了正確的編碼,但返回的Html依舊是亂碼,而事實上這並不是亂碼,而是壓縮後的html內容。

        下面我們對WebClient進行一個繼承並擴充套件,讓它支援自解壓。

public class XWebClient : WebClient {  
            protected override WebRequest GetWebRequest(Uri address) {  
                HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;  
                request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;  
                return request;  
            }  
 } 

        上面的程式碼,我們新建了一個XWebClient類,繼承自WebClient,然後,過載了WebClient的GetWebRequest事件,將AutomaticDecompression屬性的值,改為預設支援壓縮。

        剩下的,就使用XWebClient來代替WebClient,完成獲取網頁內容的工作

        XWebClient web = new XWebClient();
        byte[] pageData = web.DownloadData(url);
        string pageHtml = Encoding.Default.GetString(pageData);  //如果獲取網站頁面採用的是GB2312,則使用這句