在本节中主要讨论在Python
网络爬虫逆向中常见的一些加密数据之间的相互转化及数据类型之间的相互转化。
主要包括以下内容:
ASCII
编码Unicode
base64
str1 = 'm'
ascii_code = ord(str1)
print(ascii_code) # 109
str1 = chr(ascii_code)
print(str1) # m
由于字符串只能够对单个字符进行编码,如果想用ASCII
对字符串进行编码和解码则需要对字符串进行遍历。
原始的ASCII
编码表中没有的字符会自动使用Unicode
编码进行填充。
字符串ASCII
编码
string = 'hello world!你好'
ascii_string = [ord(i) for i in string]
print(ascii_string) # [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 20320, 22909]
ASCII
编码字符串解码
string = ''.join([chr(i) for i in ascii_string])
print(string) # hello world!你好
string = '你好,世界!'
ucode_string = string.encode('unicode_escape').decode()
print(ucode_string) # \u4f60\u597d\uff0c\u4e16\u754c\uff01
string = ucode_string.encode('utf-8').decode('unicode_escape')
print(string) # 你好,世界!
在python
中默认情况下字符串的编码是UTF-8
格式,如果是其他格式则需要在encode()
函数中传入其他参数。例如:encode('gbk')
。
byte_string = string.encode()
print(byte_string) # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81'
string = byte_string.decode('utf-8')
print(string) # 你好,世界!
在网页数据传输中字符串肯定是用到最多的,我们在进行传输的时候为了使得我们传输的内容没有那么容器被其他人破译,一般不会直接传输明文,会对其进行简单的处理再传输。但是部分过程又不支持以字节码的形式进行传输,故我们一般是将其处理为十六进制或者Base64
格式然后再进行传输。
import binascii
hex_string = binascii.b2a_hex(byte_string).decode()
print(hex_string) # 'e4bda0e5a5bdefbc8ce4b896e7958cefbc81'
hex_string = binascii.hexlify(byte_string).decode()
print(hex_string) # 'e4bda0e5a5bdefbc8ce4b896e7958cefbc81'
string = binascii.a2b_hex(hex_string)
print(string) # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81'
string = binascii.unhexlify(hex_string)
print(string) # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81'
import base64
base64_string = base64.b64encode(byte_string).decode()
print(base64_string) # 5L2g5aW977yM5LiW55WM77yB
string = base64.b64decode(base64_string).decode()
print(string) # 你好,世界!
num = 122
hex_num = hex(num)
print(hex_num) # 0x7a
hex_num = format(num, 'x')
print(hex_num) # 7a
注意这两种情况得到的结果不太一样,hex()
函数获取到的结果中包含0x
字段。
可以将代码修改成如下格式,得到的结果就保持一致了:
num = 122
hex_num = hex(num).replace('0x', '')
print(hex_num) # 7a
hex_num = format(num, 'x')
print(hex_num) # 7a
num = int(hex_num, base=16)
print(num) # 122
bin_num = bin(num)
print(bin_num) # 0b1111010
bin_num = format(num, 'b')
print(bin_num) # 1111010
与2.1
一样这两种方式得到的结果不一致,bin()
函数获取到的结果中包含0b
字段。
可修改为如下格式,使得结果保持一致。
bin_num = bin(num).replace('0b', '')
print(bin_num) # 0b1111010
bin_num = format(num, 'b')
print(bin_num) # 1111010
num = int(bin_num, base=2)
print(num) # 122
十六进制与二进制之间的相互转化,只需要使用十进制进行中间过渡即可。
bin_num = format(int(hex_num, base=16), 'b')
print(bin_num) # 1111010
hex_num = format(int(bin_num, base=2), 'x')
print(hex_num) # 7a
学习了这些转化规则后,我们就可以对字符串以及数值进行相关的加密了。
思路:字符串->
字节码->
十六进制
import binascii
# 字符串加密为十六进制编码
string = '如果你的眉眼,肯为我停留半分,又怎会不知我情比海深。'
string_hex = binascii.b2a_hex(string.encode('utf-8')).decode()
print(string_hex)
e5a682e69e9ce4bda0e79a84e79c89e79cbcefbc8ce882afe4b8bae68891e5819ce79599e58d8ae58886efbc8ce58f88e6808ee4bc9ae4b88de79fa5e68891e68385e6af94e6b5b7e6b7b1e38082
特征:结果为a-f0-9
的组合。
解码:
string = binascii.a2b_hex(string_hex).decode('utf-8')
print(string)
如果你的眉眼,肯为我停留半分,又怎会不知我情比海深。
思路:字符串->
字节码->
Base64编码
import base64
string = '如果你的眉眼,肯为我停留半分,又怎会不知我情比海深。'
string_b64= base64.b64encode(string.encode('utf-8')).decode()
print(string_b64)
5aaC5p6c5L2g55qE55yJ55y877yM6IKv5Li65oiR5YGc55WZ5Y2K5YiG77yM5Y+I5oCO5Lya5LiN55+l5oiR5oOF5q+U5rW35rex44CC
特征:a-zA-Z0-9
,以及/
和+
组成 一共64个符号,有时候有=
用来占位。
解码:
# 解码
string = base64.b64decode(string_b64).decode('utf-8')
print(string)
如果你的眉眼,肯为我停留半分,又怎会不知我情比海深。
使用str()
函数将数值转化为字符串,后续再使用字符串加密方式即可。
使用hex()
或者format()
将数值转化为十六进制,再对十六进制字符串进行加密即可。
将数值转化为二进制后取反进行加密
num = 5201314
bin_num = format(num, 'b')
min_bin_num = ''.join([str(int(i) ^ 1) for i in bin_num])
print(min_bin_num) # 01100001010001001011101
01100001010001001011101
特征:由数字0
和1
构成
解密:
bin_num = ''.join([str(int(i) ^ 1) for i in min_bin_num])
num = int(bin_num, base=2)
print(num)
5201314