最近在做Python爬虫时,遇到这么一个问题,在抓取的js文件中会有如下的字符串:
所以出现这种情况我们应该怎么处理呢?下面我们讨论一下。
1、首先,如果字符串中只存在“\x”的字符我们该怎么解决呢?
正常来说,如果只是单纯的这种字符串,Python会自动转码,但也有一些转码方法,比如字符串中这个字符串是“\x3d\x51\x53\x48”,转码方法如下,结果如图:
print('\x3d\x51\x53\x48') #这种是Python自动转码的
print(b'\x3d\x51\x53\x48'.decode()) #这个是二进制转码获得的
print('\x3d\x51\x53\x48'.encode().decode()) #这个是unicode字符串先编码再转码获得的
2、其次,如果字符串中像第一张图那样,同时存在普通字符和“\x”字符,这样该怎么解决呢?
该点主要参考:https://www.runoob.com/python3/python3-string-translate.html和https://blog.csdn.net/lilongsy/article/details/78455693
解决方法与结果如下,这三种方法都可以做到:
trantab = {key: key for key in range(1, 256)} # 制作翻译表
str = "'MlZkaW1z','MDAwMDAwMDA\x3d','Zm5vQ21zXw\x3d\x3d','c2NudUZ5ZGFlUm1zXw\x3d\x3d'"
print(repr(str)) # 该方法将对象转化为供解释器读取的形式,所以结果是两边存在双引号的字符串。
print(eval(str)) # 该方法是参考repr()方法的注释,虽然可以转码,但是会改变原字符串,此处转换成了长度为4的元组,所以不建议此方法
print(str.translate(trantab)) # 下面会介绍该方法,推荐使用该方法。
下图是该字符串在idle中的显示,显然\x3d是一体的。
另外附上str.translate()方法介绍:
translate()方法语法:
str.translate(table)
参数
table -- 翻译表,翻译表是通过 maketrans() 方法转换而来,也可以自己创建的字典。
代码示例
intab = "aeiou"
outtab = "12345"
trantab = str.maketrans(intab, outtab) # 制作翻译表
# 上面方法的字面意思就是{'a':'1', 'e':'2', 'i':'3', 'o':'4', 'u':'5'},字典的key-value形式,也就是用value来替换key的值。
# 实际上得到的字典是字符对应的ascii码,{97: 49, 111: 52, 117: 53, 101: 50, 105: 51},但也是用value对应的字符来替换key对应的字符,上面的更好理解
str = "this is string example....wow!!!"
print(str.translate(trantab))
# translate()是每个字符串自带的方法,也就是根据翻译表或者字典来将字符串中的key字符替换为value字符。
3、最后,有时候会出现这种问题,如果如果第二点中的字符串是原始字符串,也就是raw字符串,也可以用第二种方法吗?我们来做个实验:
代码如下:
trantab = {key: key for key in range(1, 256)}
str = r"'MlZkaW1z','MDAwMDAwMDA\x3d','Zm5vQ21zXw\x3d\x3d','c2NudUZ5ZGFlUm1zXw\x3d\x3d'"
# 此处的“r”表示原始字符串,或者raw字符串。
print(repr(str))
print(eval(str))
print(str.translate(trantab))
如下图。在idle中明显看出来str是普通字符串,\与x与后面的十六进制数不是一体的,是单纯的字符。
结果如下,显然,三种方法都无法直接将该字符串成功转码,虽然eval看似成功,但是将字符串转换成了元组
所以我们该如何解决这个问题呢?我们仔细看一下repr()方法的结果,将str两端加上双引号使其为字符串类型,同时将反斜杠“\”改为了“\\”,是为了转义不出错,所以我们可以将双反斜杠替换为单斜杠,然后在逆向repr就可以得到结果,代码如下,结果如下图。此处参考的网址:https://www.it1352.com/1831546.html。
from ast import literal_eval
str = r"'MlZkaW1z','MDAwMDAwMDA\x3d','Zm5vQ21zXw\x3d\x3d','c2NudUZ5ZGFlUm1zXw\x3d\x3d'"
k = repr(str).replace(r'\\', '\\')
print(literal_eval(k)) # literal_eval()方法是将repr()方法的逆向操作,即返回repr操作的字符串。
所以此处我们成功做到了将含有“\x”的原始字符串转码。
最后,此处说明一下,eval()方法是将字符串转化为python的数据类型,如转换成字典、列表、元组等,或者转换成数值类型以及转换之后做相应计算,一点示例如下: