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爬取网页时不再怕网页出现不应出现的编码了

最后提供一个练习素材:里面含有一个“锟斤拷”
地址:蓝奏云下载地址

相关文章
相关标签/搜索