爬虫与反爬是一对相生相克的死对头,道高一丈魔高一尺。作为爬虫的一方,如果知道了某个站点的数据自增ID,那么就能轻而易举把整个站点都爬下来。是不是有点耸人听闻,你去看很多大站例如油管、P站等,他们都不会轻易把业务的自增ID暴露出来,而是用一种可逆的hash字符串替代。
最常用的ID混淆就是Hashids。Hashids是一个小型的开放源代码库,可以将数字生成很短的、唯一的、非顺序的字符ID。
例如可以数字347
转换为 “yr8” 字符串,你还可以将字符串ID进行解码恢复成数字。
下面就来看看咋使用的
安装
pip install hashids
怎么使用
首选初始化一个 hashids 实例
from hashids import Hashids
hashids = Hashids()
编码(加密)
>>> id = hashids.encode(1)
>>> id
'jR'
>>> hashids.encode(123)
'Mj3'
>>> hashids.encode(1234)
'1lj'
>>> hashids.encode(12345)
'j0gW'
>>> hashids.encode(123454)
'v27AV'
生成的字符ID长度与和数值大小有关。
解码(解密)
>>> num = hashids.decode('jR')
>>> num
(1,)
>>> hashids.decode("Mj3")
(123,)
>>> hashids.decode("1lj")
(1234,)
>>> hashids.decode("j0gW")
(12345,)
>>> hashids.decode("v27AV")
(123454,)
解码后返回时一个元组。
如果你解码一个随机的字符串ID,不一定能恢复成数字,此时会返回空元组。
>>> hashids.decode("werwer")
()
因为hashid可逆,所以别人拿到字符串后也能根据字符串ID反推出数字,因此,为了避免别人猜出原始数字ID,我们在编码的时候可以指定盐值。理论上,只要盐值不被泄露,被破解的难度就加大了很多。
指定盐值
初始化 hashids时候,可以指定盐值
>>> hashids = Hashids(salt="XXXX")
>>> hashids.encode(123)
'1LY'
>>> hashids.decode("1LY")
(123,)
同样的数字使用不同的盐值编码得到的字符串是不同的,别人就无法猜出原始ID是多少了。
限制hash长度
默认情况下,数字越小,编码生成的字符串也比较短,为了将不同大小的数值转换为统一长度的字符串,在初始化hashids的时候,可以指定hash的最小长度
>>> hashids = Hashids(salt="XXXX", min_length=10)
>>> hashids.encode(123)
'PyNd1LYK3G'
限制hash的字符种类
如果你不希望hash中有大写字母,那么可以在初始化的时候,指定hash字符串的范围,例如我们可以指定为所有的小写字母
>>> hashids = Hashids(alphabet="abcdefghigklmopkrst")
>>> hashids.encode(123)
'ggdo'
需要注意的时候,alphabet至少要指定16个以上的不同字符。
hashid 简单却实用,是避免业务ID外露办法之一。
今日思考题
你知道hashids的实现原理是什么吗? 留言区第一个答对的奖励1本算法书。
关注公众号「Python之禅」,回复「1024」免费获取Python资源