httpclient訪問網站時設置Accept-Encoding為gzip,deflate返回的結果為亂碼的問題


近期迷戀上httpclient模擬各種網站登陸,瀏覽器中的開發者工具中查看請求頭信息,然后照葫蘆畫瓢寫到httpclient的請求中去,requestheader中有這么一段設置:

Accept-Encoding      gzip,deflate

之前模擬其他網站的時候這塊並沒有太在意,因為無論我在httpclient中添加上這段還是不添加,請求網站數據都沒有任何影響,也不影響網站的安全檢測,所以當時也就沒有特別關注這個設置,直到模擬登陸58同城網站的時候第一次遇到這個問題,當添加上以上的這行請求頭設置的時候,返回的網頁數據是亂碼,而且是那種各種粗體方塊的亂碼,經驗告訴我這種亂碼表現並不是簡單的編碼錯誤造成的,因為至少英文不應該出現亂碼..而且如果是簡單的gbk,utf-8之間的亂碼也不會出現這種大面積的粗體方塊..

然后想到這個Accept-Encoding,百度后知道,這個是用來設置從網站中接收的返回數據是否進行gzip壓縮.這也就解釋了為何返回的數據是大面積的粗體方塊亂碼,因為是壓縮過的數據,也就不可能進行正常解碼.

http://blog.csdn.net/zhangxinrun/article/details/5711307 這是一篇介紹gzip,deflate具體含義的博文

防止鏈接失效我直接摘抄一段:

gzip是一種數據格式,默認且目前僅使用deflate算法壓縮data部分;
deflate是一種壓縮算法,是huffman編碼的一種加強。

deflate與gzip解壓的代碼幾乎相同,可以合成一塊代碼。
區別僅有:
deflate使用inflateInit(),而gzip使用inflateInit2()進行初始化,比 inflateInit()多一個參數: -MAX_WBITS,表示處理raw deflate數據。因為gzip數據中的zlib壓縮數據塊沒有zlib header的兩個字節。使用inflateInit2時要求zlib庫忽略zlib header。在zlib手冊中要求windowBits為8..15,但是實際上其它范圍的數據有特殊作用,見zlib.h中的注釋,如負數表示raw deflate。
Apache的deflate變種可能也沒有zlib header,需要添加假頭后處理。即MS的錯誤deflate (raw deflate).zlib頭第1字節一般是0x78, 第2字節與第一字節合起來的雙字節應能被31整除,詳見rfc1950。例如Firefox的zlib假頭為0x7801,python zlib.compress()結果頭部為0x789c。
deflate 是最基礎的算法,gzip 在 deflate 的 raw data 前增加了 10 個字節的 gzheader,尾部添加了 8 個字節的校驗字節(可選 crc32 和 adler32) 和長度標識字節。

問題到這里看似已經清晰了,但是依然有一個疑點,就是我之前模擬登陸網站的時候一直會設置這個header請求頭,但是返回的數據卻不是壓縮過的.這看起來有些矛盾,經過進一步收集資料得知,瀏覽器中的都是會自動進行解壓縮的,故請求頭中都會加入這么一個編碼設置,並且網站的服務端並不是都支持這個請求頭參數,也就是說即便在請求頭中加入這么一個壓縮設置,服務器端返回數據的時候也不一定會進行壓縮才返回..至此疑問都清除..

然后接下來就好辦了,既然知道了問題的原因,那么我們用httpclient進行接收的時候也就好處理了,如果對方支持gzip壓縮處理且我們的請求頭中也加入的gzip壓縮請求頭,那么返回header中會有這么一個返回頭信息:

Content-Encoding  gzip

我們在接收返回信息的時候只需要稍微檢測一下返回頭中是否含有以上信息就可以進行相應的處理了,一段示例代碼如下:

HttpResponse rep = client.execute(post);
Header[] headers = rep.getHeaders("Content-Encoding");
boolean isGzip = false;
for(Header h:headers){
    if(h.getValue().equals("gzip")){
//返回頭中含有gzip isGzip
= true; } } String responseString = null; if(isGzip){
//需要進行gzip解壓處理 responseString
= EntityUtils.toString(new GzipDecompressingEntity(rep.getEntity())); }else{ responseString = EntityUtils.toString(rep.getEntity()); }

 

至此那個讓人抓狂的粗體方塊亂碼問題解決完畢..

 

 


免責聲明!

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



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