【日常】如何處理“火星文”亂碼

問題描述

爬蟲中常常會遇到兩種亂碼,一種是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後的字符串是正常字符串的概率是多少,做個預篩選,然後再摸索。

分享學習,共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章