自學Python八 爬蟲大坑之網頁亂碼


  Bug有時候破壞的你的興致,阻撓了保持到現在的渴望。可是,自己又非常明白,它是一種激勵,是注定要被你踩在腳下的墊腳石!

  python2.7中最頭疼的可能莫過於編碼問題了,尤其還是在window環境下,有時候總是出現莫名其妙的問題,有時候明明昨天還好好的,今天卻突然。。。遇到這種問題真的是一肚子的火。。。fuck!

  首先,在我們編寫python代碼的時候就要注意一些編碼的規范。

  1.源碼文件用#-*-coding:utf-8-*- 指定編碼並把文件保存為utf-8格式

  2.文件開頭使用from __future__ import unicode_literals   以此避免在中文前面加u,以考慮到遷移到python3。

  3.python內部是用Unicode存儲的,所有的輸入要先decode變成unicode,輸入的時候encode變成想要的編碼。在window環境下常用到的有utf-8,gbk,gb2312,gb18030等。

  4.一般網站基本都是utf-8或者gb2312。可以嘗試進行decode,然后encode 當前輸出環境的編碼格式,系統默認的編碼格式通過sys.getfilesystemencoding()。涉及到文件路徑的時候要轉換為系統默認的編碼。

  5.unicode字符串在寫入文件時必須轉換為某種字符編碼。

  在抓取網頁時,我們可以先看看該網頁的字符編碼,這些內容可以在html代碼或者f12看network中看到:

  當你得到網頁源碼后進行print的時候,那么你就要小心了。你可能會得到UnicodeEncodeError!

  你可以這樣:

1 type = sys.getfilesystemencoding()
2 #utf-8為網頁編碼,可能為gbk等
3 html = html.decode('utf-8').encode(type)

  另外還有一種萬能的方式,就是用chardet包確定網頁編碼。剛試了試 比較慢。。。需要安裝chardet包,地址為https://pypi.python.org/pypi/chardet 可以通過pip install chardet 或者 easy_install chardet安裝。使用代碼如下:

1 htmlCharsetGuess = chardet.detect(pageCode)
2 htmlCharsetEncoding = htmlCharsetGuess["encoding"]
3 htmlCode_decode = pageCode.decode(htmlCharsetEncoding)
4 type = sys.getfilesystemencoding()
5 htmlCode_encode = htmlCode_decode.encode(type)
6 print htmlCode_encode

  還有一種可能就是,你得到的網站內容是被gzip壓縮過的,這時候我們還需要去解壓縮。大部分的服務器是支持gzip壓縮的,我更改了一下HttpClient.py。我們默認就去已gzip的方式去訪問網站,得到壓縮過的內容再處理,這樣抓取速度就更快了,下面來看一下HttpClient.py的Get方法:

 1 import zlib
 2 def Get(self, url, refer=None):
 3     try:
 4       req = urllib2.Request(url)
 5       req.add_header('Accept-encoding', 'gzip')#默認以gzip壓縮的方式得到網頁內容
 6       if not (refer is None):
 7         req.add_header('Referer', refer)
 8       response = urllib2.urlopen(req, timeout=120)
 9       html = response.read()
10       gzipped = response.headers.get('Content-Encoding')#查看是否服務器是否支持gzip
11       if gzipped:
12           html = zlib.decompress(html, 16+zlib.MAX_WBITS)#解壓縮,得到網頁源碼
13       return html
14     except urllib2.HTTPError, e:
15       return e.read()
16     except socket.timeout, e:
17       return ''
18     except socket.error, e:
19       return ''

  寫了這么多發現沒寫到點子上,自己經驗比較少,然而字符編碼這種事情是需要經驗的。總結起來就是一句話,如果出現了UnicodeEncodeError錯誤了,就說明字符編碼出問題了,python解釋器也是一個工具,你需要讓他明白,所以要decode,然后他為了讓你明白所以要encode。  為了萬無一失推薦使用chardet包!

 


免責聲明!

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



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