問題描述
爬蟲中常常會遇到兩種亂碼,一種是https://blog.csdn.net/CY19980216/article/details/103116623中遇到的亂碼,嚴格來說這不是亂碼,這是字符編碼後的結果,而且它根本不亂,只是我們看不懂而已,但是計算機是可以輕易讀懂它是什麼意思的。
第二種便是如下圖所示的情況了👇
¡¾ÉϺ£ÕÐƸ£¬ÇóÖ°¡¿-Ç°³ÌÎÞÓÇ
▽奻漆桸ごㄛ⑴眥▼-ヶ最拸蚡
這些亂碼是最近筆者在爲老師爬取某就業信息網站時遇到的問題。其實之前也遇到過類似的亂碼問題,一個字符用同一種編碼方式編碼解碼當然會得到該字符本身,而這種亂碼之所以會出現,其本質是字符使用了一種編碼方式進行編碼,然後卻用另一種編碼方式去解碼,所以最終得到了一堆亂七八糟的串。
通常在爬蟲中出現這種問題是因爲許多網頁的編碼方式是ISO-8859-1,而計算機通用的編碼方式是UTF-8與GBK,爬蟲獲取數據時獲取到的是數據編碼後的串,而最終我們看到的又是計算機爲我們解碼後的結果,所以會出現這些“火星文”,通常來說只需要把這幾種常用的編碼方式兩兩搭配去對這些“火星文”編碼解碼試試,看看哪一種會出正確的結果差不多就可以了。
這種方法相對來說比較憑據經驗,做得多了有時候可以看出這些“火星文”大致是哪組編解碼出的問題,至少上面兩種情況的“火星文”顯然是不同風格的“火星文”,自然也是不同組的編解碼出的問題。凡事都有例外,這次我確實沒能試出究竟是哪兩種編碼出的問題。
問題解決
爲了方便以後快速找到哪兩種編碼方式,筆者編寫了以下方法供參考👇
# -*- coding=UTF-8 -*-
import os
"""
作者:囚生CY
平臺:CSDN
時間:2019/11/22
轉載請註明原作者
創作不易,僅供分享
"""
class Mycode():
def __init__(self,
pypath="E:/python",
codes=None,
):
self.pypath = pypath.replace("\\","/")
self.pypath = self.pypath[:-1] if self.pypath[-1]=="/" else self.pypath
if codes: self.codes = codes # 用戶指定編碼列表則使用自定義編碼方式列表
else: # 否則從python根目錄下讀取所有編碼方式
self.codes = []
for filename in os.listdir("{}/lib/encodings".format(self.pypath)):
code = filename.split(".")[0]
try: a = "1".encode(code)
except: continue
self.codes.append(code)
def transform(self,string,log=False,logpath="C:/Users/lenovo/Desktop"):
logpath = logpath.replace("\\","/")
logpath = logpath[:-1] if logpath[-1]=="/" else logpath
for x in self.codes:
for y in self.codes:
try: temp = string.encode(x).decode(y)
except: continue
result = "encode:{}\tdecode:{}\tresult:\t{}".format(x,y,temp)
print(result)
if log:
with open("{}/mycode_log.txt","a") as f:
f.write("{}\n".format(result))
if __name__ == "__main__":
mycode = Mycode()
mycode.transform("¡¾ÉϺ£ÕÐƸ£¬ÇóÖ°¡¿-Ç°³ÌÎÞÓÇ")
注意到,python的根目錄下的Lib文件夾中的encodings文件夾中存了一百多種編碼方式的py文件,如筆者的python根目錄在E:/python/,則該文件夾在E:/python/Lib/encodings/👇
這些文件的文件名恰爲編碼的名稱,筆者試圖遍歷所有的“編碼方式對”去找到正確的處理方式,上面代碼運行結果如下👇
可以看到使用charmap編碼,gb18030/gb2312/gbk解碼即可使得這串“火星文”變成能夠讀懂的漢字。
當然這種“編碼方式對”未必唯一,有人說一百多種編碼方式對得有一萬多種情況,這該怎麼找呢?
筆者推薦視力好的直接翻了找,視力差的去配副好點的眼鏡,如果瞎了的話就列個常用字符庫(中英文都要有,但一般來說出現火星文都是中文的問題),多寫點代碼大致判斷一下上圖result後的字符串是正常字符串的概率是多少,做個預篩選,然後再摸索。
分享學習,共同進步!