1. 程式人生 > >python2 編碼問題小解決;sys;unicode-escape

python2 編碼問題小解決;sys;unicode-escape

今天作者想要分享的是自己在爬取網站過程中一些簡單的編碼問題,當然說是簡單問題作者也是搜尋了很久,今天分享下來方便以後自己在遇到這類問題更好的解決。
環境:python2
目標網站種的內容如下圖:
這裡寫圖片描述
從爬取出來的程式碼來看這些欄位並沒有亂碼,但是啊在作者進行提取的過程種發現提取到的內容並不是正常的內容,作者這裡簡單分享一下自己。後續會持續分享一些編碼的問題。

資訊的提取:

car_res = etree.HTML(car_res.content)
all_car = car_res.xpath('//div[@name="SearchKey"]/@id')
for each_car in
all_car[1:]: print each_car

但是獲取的結果並不如意:

粤BF7983_13300768817
粤BGD695_13300768868
粤BV9402_13725023706
粤BEU601_13816018047
粤B35CU5_13816029721
粤B8FP29_13816072371
粤B89DH5_13820034541
粤BDA851_13821008623
粤BF7983_13300768817

從結果來看本應該是車牌號而此時的獲取卻亂碼了,作者不僅懷疑為什麼,就去看網頁的原始碼看看網頁種的charset編碼格式是什麼?
這裡寫圖片描述
從截圖來看,網頁中的編碼是utf-8

那麼便考慮當自己採集的時候可以先獲取位元組然後通過utf-8 進行解碼豈不是美滋滋,這樣問題應該就會解決了。
這裡寫圖片描述
當然我們知道在python2.7中.text表示的是位元組,.content 是字元,所以筆者在工作中的程式碼是:

car_res = etree.HTML(car_res.text.decode('utf-8'))
all_car = car_res.xpath('//div[@name="SearchKey"]/@id')
car_infos = []
for each_car in all_car[1:]:
    print each_car

然而不幸的是發現結果仍然是:

粤BF7983_13300768817
粤BGD695_13300768868
粤BV9402_13725023706
粤BEU601_13816018047
粤B35CU5_13816029721
粤B8FP29_13816072371
粤B89DH5_13820034541

真滴是尷尬……………..便想到了重新進行系統編碼的設定,通過匯入sys模組

import sys

reload(sys)  // 為什麼新增你可參考連結:http://www.360doc.com/content/15/0105/15/9934052_438371998.shtml
sys.setdefaultencoding("utf-8")

關於為什麼要用這個模組,首先作者理解的解釋一下:Python 預設指令碼檔案都是 UTF-8 編碼的,當檔案中有非 UTF-8 編碼範圍內的字元的時候就要使用”編碼指示”來修正. 關於 sys.defaultencoding,這個在解碼沒有明確指明解碼方式的時候使用。
具體的理解可以這樣理解:

res = '這是程式碼'
print (res.encode('gb2312'))  // 然而結果卻提示的錯誤是

這裡寫圖片描述
這句程式碼將 res 重新編碼為 gb2312的格式,即進行 unicode -> str 的轉換。因為 res本身就是 str 型別的,因此
Python 會自動的先將 res 解碼為 unicode ,然後再編碼成 gb2312。因為解碼是python自動進行的,而我們有沒有指明解碼方式,python 就會使用 sys.defaultencoding 指明的方式來解碼。很多情況下 sys.defaultencoding 是
ANSCII,顯然的我們的res不是這個型別。拿上面的情況來說,我的 sys.defaultencoding 是 anscii,而 res 的編碼方式和檔案的編碼方式一致,是 utf8 的,所以出錯了。所以這個時候具體的解決辦法是:

# coding=utf-8
res = '這是程式碼'
print (res.decode('utf-8').encode('gb2312'))

當然了也可以通過更改 sys.defaultencoding 為檔案的編碼方式

#coding=utf-8

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

res = '這是程式碼'
print (res.encode('gb2312')) // 結果就是正確的當然這只是舉例,gb2312也可以是任何的編碼格式。

好了言歸正傳,在本文中筆者便想到這種方法,然而卻依然是錯誤的編碼格式,這時候筆者採用了兩種解決的方式:
第一種:

car_res = res.get(url=car_url, headers=car_headers)
car_res.encoding = "utf-8"  // 對獲取到的內容通過utf-8進行整體的編碼
car_res = etree.HTML(car_res.text)
all_car = car_res.xpath('//div[@name="SearchKey"]/@id')
car_infos = []
for each_car in all_car[1:]:
    print each_car

結果如下:

粵BF7983_13300768817
粵BGD695_13300768868
粵BV9402_13725023706
粵BEU601_13816018047
粵B35CU5_13816029721
粵B8FP29_13816072371
粵B89DH5_13820034541
粵BDA851_13821008623

顯然結果是自己想要的。
第二種方法:

car_res = etree.HTML(unicode(car_res.content, 'utf-8', errors='replace'))  
all_car = car_res.xpath('//div[@name="SearchKey"]/@id')
car_infos = []
for each_car in all_car[1:]:
    print each_car

結果同樣是自己想要的:

粵BF7983_13300768817
粵BGD695_13300768868
粵BV9402_13725023706
粵BEU601_13816018047
粵B35CU5_13816029721
粵B8FP29_13816072371
粵B89DH5_13820034541

unicode(car_res.content, 'utf-8', errors='replace') unicode 這個方法可以點選去看其返回值

def __init__(self, string=u'', encoding=None, errors='strict'): # known special case of unicode.__init__
    """
    unicode(object='') -> unicode object
    unicode(string[, encoding[, errors]]) -> unicode object

    Create a new Unicode object from the given encoded string.
    encoding defaults to the current default string encoding.
    errors can be 'strict', 'replace' or 'ignore' and defaults to 'strict'.
    # (copied from class doc)
    """
    pass

好了,今天的分享到這裡就結束了。後續如果遇到編碼問題會持續分享。
還有一個問題是作者在解析欄位的時候遇到的

dd = "苏MJ6368"
dd = dd.replace('&#x', '\\u').replace(';', '').decode('unicode-escape')
print dd  參考:https://www.cnblogs.com/leomei91/p/7685797.html