Python字節的修改,踩坑路程

一個網頁中有不一樣的編碼,其實就是網頁中穿插着unicode沒法映射的編碼,使用requests爬蟲會直接失敗html

1、 踩坑路程1

1. 強制類型轉換

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

2. 中間人

既然我有了一個字符串類型的字節,雖然它是字符串類型的,可是它的內容是字節啊,因此咱們能夠建一個文本,以二進制的方式讀寫不就好了?指針

這裏就不給代碼了,和上面的相似,以二進制的方式讀寫,傳入值必須是字節型的也就是bytes,但是咱們不是沒法轉換來着嗎?code

3. 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依然的我行我素,好了既然咱們知道錯誤在什麼地方了,下一步就該解決了,離解決方法是愈來愈近了

2、 終於成功了

1. 增長一個偏移量

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"))

雲追逐雨

2. 讓其輪空

在咱們須要的時候不讓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"))

雲追逐雨

3. 更爲簡練的寫法

原來能夠直接像是列表同樣刪除其索引,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"))

雲追逐雨

3、 總結

建議使用三種寫法,更解決,前面能夠加一個判斷,使其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爬取網頁時不再怕網頁出現不應出現的編碼了

最後提供一個練習素材:裏面含有一個「錕斤拷」
地址:藍奏雲下載地址

相關文章
相關標籤/搜索