Python网站手机号码解密的一种方法

Python网站手机号码解密的一种方法

黄页88网站反爬措施对手机号进行了一些加密处理。这里介绍一下怎么解密手机号码的方法。

首先,我们看一下网站显示的手机号是这样的:

显示的手机号

使用ctrl c复制粘贴后变成了这样:

复制后的手机号码

而实际上,用Python爬虫获取到的内容是这样的:

爬虫获取到的数据

经过分析,发现这些数据其实有以下特点:

  1. 每次刷新网页,编码会变
  2. 编码之间其实有关系(实际上就是0-9转换成了16进制)

所以,我们的思路就是:

  1. 确定手机号码开头1对应的是第一个编码
  2. 然后根据第一个编码获取0-9对应的16进制编码
  3. 在通过编码检索出这串编码对应的电话号码

步骤:

  1. 首先爬取到电话号码的代码

code_list='򈊷򈊻򈊼򈊹򈊷򈊸򈊼򈊽򈊽򈊽&#x882b7'

  1. 要转换为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'
  1. 上面是个字符串,要对每个编码进行处理,还是需要转换成列表,刚好对应11个号码

# 转换成列表
code_list=code_list.split(';')

In [6]: code_list
Out[6]: 
['0x882b7',
 '0x882bb',
 '0x882bc',
 '0x882b9',
 '0x882b7',
 '0x882b8',
 '0x882bc',
 '0x882bd',
 '0x882bd',
 '0x882bd',
 '0x882b7']
  1. 因为手机号码的第一位是1,所以确定第一位16进制对应的10进制值,就可以知道0-9对应的10进制值是多少

# 确定第一个号码1对应的10进制值
c1=int(code_list[0],base=16)

In [8]: c1
Out[8]: 557751
  1. 知道了1对应的值,就创建0-9对应的10进制值

# 创建0-9对应的10进制值
int_list=range(c1-1,c1+9)

In [10]: int_list
Out[10]: range(557750, 557760)
  1. 然后将上面的数据转换成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']
  1. 创建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']
  1. 将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'}
  1. 最后一步就是通过字典查询并组装成最终的电话号码了(为了避免各种纠纷:这里的电话号码后面几位进行了修改,不是真实的用户电话)

# 见证奇迹的时刻,把电话号码翻译过来
phone="".join([code_dict[p] for p in code_list])

In [18]: phone
Out[18]: '15631267771'

所有代码如下:

code_list='򈊷򈊻򈊼򈊹򈊷򈊸򈊼򈊽򈊽򈊽&#x882b7'
# 替换&#为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),或者填的是固定电话的情况,所以无法适用于这些情况。

shanlin

发表评论