一個網頁中有不一樣的編碼,其實就是網頁中穿插着
unicode
沒法映射的編碼,使用requests
爬蟲會直接失敗html
在
requests
中能夠直接獲取到網頁源碼的二進制數據,其實也就是還沒有進行編碼的字節,在Python中以十六進制的形式展示,格式就是下面這種app
data="你好世界!" print(data.encode("utf-8"))
那麼咱們就有了思路,咱們可不能夠在它仍是字節剔除掉亂碼的部分,而後轉換成字節,從新編碼ide
data=b"\xe4\xbd\xa0" # 轉換成字符串 data=str(data) print(data) # 轉換成字節 data=bytes(data,"utf-8") print("字節形式:",data) print("解碼成UTF-8文本",data.decode("utf-8"))
很明顯失敗了,在把他轉換成字節的時候多了
\
,也就是把\xe4\xbd\xa0
的字節轉換成字節,也就變成了\\xe4\\xbd\\xa0
,這種字節格式是明顯沒法解碼成功的,最終就是解碼成了\xe4\xbd\xa0
函數問題彷佛出如今了
data=bytes(data,"utf-8")
多了utf-8
,去掉試試ui
報錯了,這個問題相似於c語言的指針,指向指針的指針編碼
若是能直接轉換的話,這個問題直接就能解決了,但是並不能3d
既然我有了一個字符串類型的字節,雖然它是字符串類型的,可是它的內容是字節啊,因此咱們能夠建一個文本,以二進制的方式讀寫不就好了?指針
這裏就不給代碼了,和上面的相似,以二進制的方式讀寫,傳入值必須是字節型的也就是
bytes
,但是咱們不是沒法轉換來着嗎?code
bytearray
單字節讀取這個命令能夠對字節單個讀取修改,我彷佛離正確的答案愈來愈近了htm
data=b"\xe4\xbd\xa0" data=bytearray(data) print(hex(data[0])) print(hex(data[1]))
不過別高興的太早,我封裝了一個函數,按照其邏輯來講的話是很完美的,是應該能正確的,但是Python有Python的邏輯
def Binary(text,content): # text是一個列表 # content是requests獲取到的字節 content=bytearray(content) data=bytearray() sum=0 k=0 # 開始比對 for i in range(len(content)): for j in range(len(text)): # 防止超出範圍 if i+j>=len(content): break; # 若是第一個相同那就比對後面的幾個 if content[i+j]==text[j]: sum=sum+1 # 若是所有相同,那麼他就是相等的,讓i往前移動len(text)-1個位置 if sum==len(text): i=i+len(text)-1 else: data.append(content[i]) sum=0 return data
爲何會失敗?由於Python的for循環 i沒法更改,就像是下面
a=10 for i in range(a): print(i) i=i+2
這個明顯不符合咱們的預期啊,該死的i依然的我行我素,好了既然咱們知道錯誤在什麼地方了,下一步就該解決了,離解決方法是愈來愈近了
def Binary(text,content): # text是一個列表 # content是requests獲取到的字節 content=bytearray(content) data=bytearray() sum=0 k=0 # 開始比對,減小次數,避免溢出 for i in range(len(content)-len(text)): for j in range(len(text)): # 若是第一個相同那就比對後面的幾個 if content[i+j]==text[j]: sum=sum+1 # 若是所有相同,那麼他就是相等的,讓i往前移動len(text)-1個位置 if sum==len(text): k=len(text)-1 else: data.append(content[i+k]) sum=0 return data # 獲取網頁 r=requests.get("https://www.biquge.com.cn/book/7787/192921.html") # 須要剔除的字節 text=[239,191,189] # 調用函數 content=Binary(text,r.content) content=bytes(content) # 把字節解碼成Utf-8的文本 print(content.decode("utf-8"))
在咱們須要的時候不讓data添加字節
def Binary(text,content): # text是一個列表 # content是requests獲取到的字節 content=bytearray(content) data=bytearray() sum=0 k=0 # 開始比對 for i in range(len(content)): if k<=0: for j in range(len(text)): # 防止索引超出範圍 if i+j>=len(content): break # 若是第一個相同那就比對後面的幾個 if content[i+j]==text[j]: sum=sum+1 # 若是所有相同,賦值給k if sum==len(text): k=sum sum=0 # 利用k讓for輪空 if k>0: k=k-1 continue data.append(content[i]) sum=0 return data # 獲取網頁 r=requests.get("https://www.biquge.com.cn/book/7787/192921.html") text=[239,191,189] content=Binary(text,r.content) content=bytes(content) # 把字節解碼成Utf-8的文本 print(content.decode("utf-8"))
原來能夠直接像是列表同樣刪除其索引,
data.remove
不能用,不知道爲何
def Binary(text,content): # text是一個列表 # content是requests獲取到的字節 content=bytearray(content) data=bytearray() sum=0 k=[] # 開始比對 for i in range(len(content)-len(text)): for j in range(len(text)): if content[i+j]==text[j]: sum=sum+1 if sum==len(text): for j in range(len(text)): k.append(i+j) sum=0 for i in range(len(k)): del content[k[0]] return content r=requests.get("https://www.biquge.com.cn/book/7787/192921.html") text=[239,191,189] content=Binary(text,r.content) print(content.decode("utf-8"))
建議使用三種寫法,更解決,前面能夠加一個判斷,使其
del content[0]
不會出現問題
def Binary(text,content): # text是一個列表 # content是requests獲取到的字節 content=bytearray(content) data=bytearray() sum=0 k=[] # 開始比對 for i in range(len(content)-len(text)): for j in range(len(text)): if content[i+j]==text[j]: sum=sum+1 if sum==len(text): for j in range(len(text)): k.append(i+j) sum=0 # 若是不等那就表明着沒有找到,返回原來的字節值就行 if len(k)!=len(text): return content for i in range(len(k)): # content.pop(k[0]) del content[k[0]] return content r=requests.get("https://www.baidu.com") text=[239,191,189] content=Binary(text,r.content) print(content.decode("utf-8"))
花了好長的時間,終於解決好了,可謂是一頓操做猛如虎,最後只解決一個字符問題,大寫的尷尬
有能力的大佬能夠多收集一些
「錕斤拷」
造成一個庫,這樣在用requests爬取網頁時不再怕網頁出現不應出現的編碼了最後提供一個練習素材:裏面含有一個
「錕斤拷」
地址:藍奏雲下載地址