黄页88网站反爬措施对手机号进行了一些加密处理。这里介绍一下怎么解密手机号码的方法。
首先,我们看一下网站显示的手机号是这样的:
显示的手机号
使用ctrl c复制粘贴后变成了这样:
复制后的手机号码
而实际上,用Python爬虫获取到的内容是这样的:
爬虫获取到的数据
经过分析,发现这些数据其实有以下特点:
- 每次刷新网页,编码会变
- 编码之间其实有关系(实际上就是0-9转换成了16进制)
所以,我们的思路就是:
- 确定手机号码开头1对应的是第一个编码
- 然后根据第一个编码获取0-9对应的16进制编码
- 在通过编码检索出这串编码对应的电话号码
步骤:
- 首先爬取到电话号码的代码
code_list='򈊷򈊻򈊼򈊹򈊷򈊸򈊼򈊽򈊽򈊽򈊷'
- 要转换为16进制,需要把&#替换为0
# 替换&#为0,用于后面直接转换为10进制数
code_list=code_list.replace("&#","0")
In [4]: code_list
Out[4]: '0x882b7;0x882bb;0x882bc;0x882b9;0x882b7;0x882b8;0x882bc;0x882bd;0x882bd;0x882bd;0x882b7'
- 上面是个字符串,要对每个编码进行处理,还是需要转换成列表,刚好对应11个号码
# 转换成列表
code_list=code_list.split(';')
In [6]: code_list
Out[6]:
['0x882b7',
'0x882bb',
'0x882bc',
'0x882b9',
'0x882b7',
'0x882b8',
'0x882bc',
'0x882bd',
'0x882bd',
'0x882bd',
'0x882b7']
- 因为手机号码的第一位是1,所以确定第一位16进制对应的10进制值,就可以知道0-9对应的10进制值是多少
# 确定第一个号码1对应的10进制值
c1=int(code_list[0],base=16)
In [8]: c1
Out[8]: 557751
- 知道了1对应的值,就创建0-9对应的10进制值
# 创建0-9对应的10进制值
int_list=range(c1-1,c1+9)
In [10]: int_list
Out[10]: range(557750, 557760)
- 然后将上面的数据转换成16进制
# 将其转换为hex
hex_list=[str(hex(i)) for i in int_list]
In [12]: hex_list
Out[12]:
['0x882b6',
'0x882b7',
'0x882b8',
'0x882b9',
'0x882ba',
'0x882bb',
'0x882bc',
'0x882bd',
'0x882be',
'0x882bf']
- 创建0-9的列表,并转换成字符串,方便后面组装成电话号码(这里0-9的顺序和hex_list里面的顺序是一一对应的)
# 创建0-9的数字对应列表
str_list=[str(i) for i in range(0,10)]
In [14]: str_list
Out[14]: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
- 将hex和0-9的字符串组装成字典,方便后面查询
# 组装成字典方便对应
code_dict=dict(zip(hex_list,str_list))
In [16]: code_dict
Out[16]:
{'0x882b6': '0',
'0x882b7': '1',
'0x882b8': '2',
'0x882b9': '3',
'0x882ba': '4',
'0x882bb': '5',
'0x882bc': '6',
'0x882bd': '7',
'0x882be': '8',
'0x882bf': '9'}
- 最后一步就是通过字典查询并组装成最终的电话号码了(为了避免各种纠纷:这里的电话号码后面几位进行了修改,不是真实的用户电话)
# 见证奇迹的时刻,把电话号码翻译过来
phone="".join([code_dict[p] for p in code_list])
In [18]: phone
Out[18]: '15631267771'
所有代码如下:
code_list='򈊷򈊻򈊼򈊹򈊷򈊸򈊼򈊽򈊽򈊽򈊷'
# 替换&#为0,用于后面直接转换为10进制数
code_list=code_list.replace("&#","0")
# 转换成列表
code_list=code_list.split(';')
# 确定第一个号码1对应的10进制值
c1=int(code_list[0],base=16)
# 创建0-9对应的10进制值
int_list=range(c1-1,c1+9)
# 将其转换为hex
hex_list=[str(hex(i)) for i in int_list]
# 创建0-9的数字对应列表
str_list=[str(i) for i in range(0,10)]
# 组装成字典方便对应
code_dict=dict(zip(hex_list,str_list))
# 见证奇迹的时刻,把电话号码翻译过来
phone="".join([code_dict[p] for p in code_list])
上面这个过程最主要的一点是,我们假设编码的第一位是1,其他号码都是通过这个推算来的。但无法避免有些手机号码填错(第一位不是1),或者填的是固定电话的情况,所以无法适用于这些情况。
网友评论