完善功能
This commit is contained in:
21
README.md
21
README.md
@@ -1,2 +1,21 @@
|
|||||||
# GetQQInfo
|
# GetQQInfo
|
||||||
我超,盒
|
# 我超,盒
|
||||||
|
#
|
||||||
|
### 本项目通过使用 {imagehash} 对比两个图片的相似度,从而实现通过头像获取QQ号
|
||||||
|
|
||||||
|
|
||||||
|
- type = 1 :通过Mysql数据库查询qq号
|
||||||
|
- type = 2 :通过网络下载头像查询qq号
|
||||||
|
- type = 3 :下载TargetRange范围内的qq号,解析每个qq号的头像后,上传Hash值到Mysql服务器
|
||||||
|
|
||||||
|
### Mysql数据库配置:
|
||||||
|
|
||||||
|
```mysql
|
||||||
|
CREATE TABLE example (
|
||||||
|
id INT unsigned AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
hash TINYBLOB NULL
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
头像下载地址:https://q1.qlogo.cn/g?b=qq&nk=114514&s=0
|
||||||
64
Thread.py
64
Thread.py
@@ -1,55 +1,46 @@
|
|||||||
import threading
|
import pymysql, threading
|
||||||
import pymysql
|
from Tools import config, download_image, Hash, remove_image, compare, Image, imagehash, os, logging, clean_image
|
||||||
from tools import *
|
|
||||||
|
|
||||||
|
Myconn = pymysql.connect(
|
||||||
|
host=str(config['mysql']['host']),
|
||||||
|
user=str(config['mysql']['user']),
|
||||||
|
password=str(config['mysql']['password']),
|
||||||
|
database=str(config['mysql']['database'])
|
||||||
|
)
|
||||||
|
|
||||||
|
exit_flag = False
|
||||||
|
|
||||||
class UploadThread(threading.Thread):
|
class UploadThread(threading.Thread):
|
||||||
def __init__(self, uploadqqnumber):
|
def __init__(self, uploadqqnumber):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.uploadqqnumber = uploadqqnumber
|
self.uploadqqnumber = uploadqqnumber
|
||||||
self.conn = pymysql.connect(
|
self.conn = Myconn
|
||||||
host='192.168.9.1', # 你的 MySQL 主机
|
|
||||||
user='root', # 你的 MySQL 用户
|
|
||||||
password='123456', # 你的 MySQL 密码
|
|
||||||
database='qqinfo' # 你要连接的数据库
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def conn_close(self):
|
|
||||||
self.conn.close()
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
print(f'我是上传线程{self.uploadqqnumber}')
|
logging.debug(f'我是上传线程{self.uploadqqnumber}')
|
||||||
if download_image(self.uploadqqnumber):
|
if download_image(self.uploadqqnumber):
|
||||||
Hash(self.conn).tomysql(self.uploadqqnumber)
|
Hash(self.conn).tomysql(self.uploadqqnumber)
|
||||||
print('上传成功')
|
logging.info(f'上传成功: {self.uploadqqnumber}')
|
||||||
remove_image(self.uploadqqnumber)
|
remove_image(self.uploadqqnumber)
|
||||||
|
self.conn.close()
|
||||||
|
|
||||||
|
|
||||||
class FindThread(threading.Thread):
|
class FindThread(threading.Thread):
|
||||||
def __init__(self, TargetImageHash):
|
def __init__(self, TargetImageHash):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.TargetImageHash = TargetImageHash
|
self.TargetImageHash = TargetImageHash
|
||||||
self.conn = pymysql.connect(
|
self.conn = Myconn
|
||||||
host='192.168.9.1', # 你的 MySQL 主机
|
|
||||||
user='root', # 你的 MySQL 用户
|
|
||||||
password='123456', # 你的 MySQL 密码
|
|
||||||
database='qqinfo' # 你要连接的数据库
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def conn_close(self):
|
|
||||||
self.conn.close()
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
print(f'我是查询线程{self.TargetImageHash}')
|
global exit_flag
|
||||||
|
logging.debug(f'我是查询线程{self.TargetImageHash}')
|
||||||
res = Hash(self.conn).getqq(self.TargetImageHash)
|
res = Hash(self.conn).getqq(self.TargetImageHash)
|
||||||
if res != 'error':
|
if res != 'error':
|
||||||
print(f'查询成功,QQ号是: {res}')
|
logging.info(f'查询成功,QQ号是: {res}')
|
||||||
exit()
|
exit_flag = True
|
||||||
|
self.conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -61,13 +52,20 @@ class ByNetFindThread(threading.Thread):
|
|||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
global exit_flag
|
||||||
if download_image(self.findqqnumber):
|
if download_image(self.findqqnumber):
|
||||||
FindImage = Image.open(str(f'./img/{self.findqqnumber}.jpg'))
|
FindImage = Image.open(str(f'./img/{self.findqqnumber}.jpg'))
|
||||||
|
if FindImage.mode == 'P' and 'transparency' in FindImage.info:
|
||||||
|
FindImage = FindImage.convert('RGBA')
|
||||||
FindImageHash = bytes.fromhex(str(imagehash.average_hash(FindImage)))
|
FindImageHash = bytes.fromhex(str(imagehash.average_hash(FindImage)))
|
||||||
res = compare(self.TargetImageHash, FindImageHash)
|
res = compare(self.TargetImageHash, FindImageHash)
|
||||||
if res-99.9 >= 0 :
|
if res-99.9 >= 0 :
|
||||||
print(f'找到QQ号了:{self.findqqnumber}')
|
logging.info(f'找到QQ号了:{self.findqqnumber}')
|
||||||
|
if os.path.exists(f'./img/congratulations_{self.findqqnumber}.jpg'):
|
||||||
|
os.remove(f'./img/congratulations_{self.findqqnumber}.jpg')
|
||||||
os.rename(f'./img/{self.findqqnumber}.jpg',f'./img/congratulations_{self.findqqnumber}.jpg')
|
os.rename(f'./img/{self.findqqnumber}.jpg',f'./img/congratulations_{self.findqqnumber}.jpg')
|
||||||
exit()
|
exit_flag = True
|
||||||
print(f'[{self.findqqnumber}]的相似度是:{res}')
|
clean_image()
|
||||||
remove_image(self.findqqnumber)
|
os._exit(0)
|
||||||
|
logging.info(f'[{self.findqqnumber}]的相似度是:{res}%')
|
||||||
|
remove_image(self.findqqnumber)
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import os
|
|
||||||
import requests
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import imagehash
|
import imagehash, configparser, requests, os, logging, re
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read('config.cfg')
|
||||||
|
logging.basicConfig(level=int(config['logging']['level']), format='%(asctime)s - %(levelname)s - %(message)s')
|
||||||
|
# logging.debug("这是调试信息")
|
||||||
|
# logging.info("这是信息级别的日志")
|
||||||
|
# logging.warning("这是警告级别的日志")
|
||||||
|
# logging.error("这是错误级别的日志")
|
||||||
|
# logging.critical("这是严重错误级别的日志")
|
||||||
|
|
||||||
class Hash:
|
class Hash:
|
||||||
def __init__(self, conn):
|
def __init__(self, conn):
|
||||||
@@ -19,9 +25,9 @@ class Hash:
|
|||||||
_cursor.execute('SELECT hash FROM image_hashes WHERE id = (%s)', (_qqnumber,))
|
_cursor.execute('SELECT hash FROM image_hashes WHERE id = (%s)', (_qqnumber,))
|
||||||
byte_data_from_db = _cursor.fetchone()
|
byte_data_from_db = _cursor.fetchone()
|
||||||
if byte_data_from_db is None:
|
if byte_data_from_db is None:
|
||||||
print(f'{_qqnumber}不在数据库内')
|
logging.info(f'{_qqnumber}不在数据库内')
|
||||||
else:
|
else:
|
||||||
print(f'从数据库获取的Hash号: {byte_data_from_db[0]}')
|
logging.debug(f'从数据库获取的Hash号: {byte_data_from_db[0]}')
|
||||||
_cursor.close()
|
_cursor.close()
|
||||||
return byte_data_from_db[0]
|
return byte_data_from_db[0]
|
||||||
|
|
||||||
@@ -36,10 +42,10 @@ class Hash:
|
|||||||
_cursor.execute('SELECT id FROM image_hashes WHERE hash = (%s)', (_hash,))
|
_cursor.execute('SELECT id FROM image_hashes WHERE hash = (%s)', (_hash,))
|
||||||
byte_data_from_db = _cursor.fetchone()
|
byte_data_from_db = _cursor.fetchone()
|
||||||
if byte_data_from_db is None:
|
if byte_data_from_db is None:
|
||||||
print('Hash值不存在')
|
logging.info('Hash值不存在')
|
||||||
return 'error'
|
return 'error'
|
||||||
else:
|
else:
|
||||||
print(f'从数据库获取的QQ号: {byte_data_from_db[0]}')
|
logging.debug(f'从数据库获取的QQ号: {byte_data_from_db[0]}')
|
||||||
_cursor.close()
|
_cursor.close()
|
||||||
return byte_data_from_db[0]
|
return byte_data_from_db[0]
|
||||||
|
|
||||||
@@ -50,6 +56,8 @@ class Hash:
|
|||||||
:param: _qqnumber: QQ号
|
:param: _qqnumber: QQ号
|
||||||
"""
|
"""
|
||||||
_img = Image.open(str(f'./img/{_qqnumber}.jpg'))
|
_img = Image.open(str(f'./img/{_qqnumber}.jpg'))
|
||||||
|
if _img.mode == 'P' and 'transparency' in _img.info:
|
||||||
|
_img = _img.convert('RGBA')
|
||||||
_byte_data = bytes.fromhex(str(imagehash.average_hash(_img)))
|
_byte_data = bytes.fromhex(str(imagehash.average_hash(_img)))
|
||||||
_cursor = self.conn.cursor()
|
_cursor = self.conn.cursor()
|
||||||
_cursor.execute("""
|
_cursor.execute("""
|
||||||
@@ -58,7 +66,7 @@ class Hash:
|
|||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
hash = VALUES(hash)
|
hash = VALUES(hash)
|
||||||
""", (_qqnumber, _byte_data))
|
""", (_qqnumber, _byte_data))
|
||||||
print(f'[{_qqnumber}]:{_byte_data}')
|
logging.debug(f'[{_qqnumber}]:{_byte_data}')
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
_cursor.close()
|
_cursor.close()
|
||||||
|
|
||||||
@@ -106,10 +114,10 @@ def download_image(_qqnumber):
|
|||||||
# 保存图片
|
# 保存图片
|
||||||
with open(image_name, 'wb') as f:
|
with open(image_name, 'wb') as f:
|
||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
print(f'图片已保存为 {image_name}')
|
logging.debug(f'图片已保存为 {image_name}')
|
||||||
return 1
|
return 1
|
||||||
else:
|
else:
|
||||||
print(f'下载图片失败,错误码:{response.status_code}')
|
logging.info(f'下载图片失败,错误码:{response.status_code}')
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@@ -124,4 +132,21 @@ def remove_image(_qqnumber):
|
|||||||
os.remove(f'./img/{_qqnumber}.jpg')
|
os.remove(f'./img/{_qqnumber}.jpg')
|
||||||
return 1
|
return 1
|
||||||
else:
|
else:
|
||||||
print(f'没有找到这个QQ号的图片:{_qqnumber}')
|
logging.info(f'没有找到这个QQ号的图片:{_qqnumber}')
|
||||||
|
|
||||||
|
|
||||||
|
def clean_image():
|
||||||
|
# 定义正则表达式匹配10位数字的文件名
|
||||||
|
pattern = r'^\d{10}\.jpg$'
|
||||||
|
# 获取./img目录下的所有文件
|
||||||
|
img_dir = './img'
|
||||||
|
# 遍历目录中的所有文件
|
||||||
|
for filename in os.listdir(img_dir):
|
||||||
|
# 检查文件是否符合10位数字.jpg的模式
|
||||||
|
if re.match(pattern, filename):
|
||||||
|
file_path = os.path.join(img_dir, filename)
|
||||||
|
try:
|
||||||
|
os.remove(file_path)
|
||||||
|
logging.debug(f"已删除文件: {file_path}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.debug(f"删除文件 {file_path} 时发生错误: {e}")
|
||||||
22
config.cfg
Normal file
22
config.cfg
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[settings]
|
||||||
|
type = 2
|
||||||
|
TargetRange = 1310371400, 1310379530
|
||||||
|
TargetImage = ./img/target5.jpg
|
||||||
|
|
||||||
|
[mysql]
|
||||||
|
host = 192.168.9.1
|
||||||
|
user = root
|
||||||
|
password = 123456
|
||||||
|
database = qqinfo
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
level = 20
|
||||||
|
|
||||||
|
;CRITICAL = 50
|
||||||
|
;FATAL = CRITICAL
|
||||||
|
;ERROR = 40
|
||||||
|
;WARNING = 30
|
||||||
|
;WARN = WARNING
|
||||||
|
;INFO = 20
|
||||||
|
;DEBUG = 10
|
||||||
|
;NOTSET = 0
|
||||||
43
main.py
43
main.py
@@ -1,24 +1,35 @@
|
|||||||
from Thread import pymysql, UploadThread, FindThread, ByNetFindThread , threading
|
from Thread import UploadThread, FindThread, ByNetFindThread
|
||||||
from tools import imagehash, Image, download_image
|
from Tools import imagehash, Image, os, config
|
||||||
|
|
||||||
# download_image(1310371422)
|
type = int(config['settings']['type'])
|
||||||
TargetRange = [1310372220, 1310372400]
|
TargetRange = list(map(int, config['settings']['TargetRange'].split(',')))
|
||||||
TargetImage = Image.open(str(f'./img/target3.jpg'))
|
TargetImagePath = config['settings']['TargetImage']
|
||||||
|
TargetImage = Image.open(TargetImagePath)
|
||||||
TargetImageHash = bytes.fromhex(str(imagehash.average_hash(TargetImage)))
|
TargetImageHash = bytes.fromhex(str(imagehash.average_hash(TargetImage)))
|
||||||
baseArr = TargetRange[0]
|
baseArr = TargetRange[0]
|
||||||
|
if not os.path.exists('img'):
|
||||||
|
os.makedirs('img')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
Thread = FindThread(TargetImageHash)
|
if type == 1:
|
||||||
Thread.start()
|
Thread = FindThread(TargetImageHash)
|
||||||
|
Thread.start()
|
||||||
|
|
||||||
# while baseArr<TargetRange[1]:
|
elif type == 2:
|
||||||
# Thread = ByNetFindThread(TargetImageHash, baseArr)
|
while baseArr < TargetRange[1]:
|
||||||
# Thread.start()
|
Thread = ByNetFindThread(TargetImageHash, baseArr)
|
||||||
# baseArr += 1
|
Thread.start()
|
||||||
|
baseArr += 1
|
||||||
# while baseArr<=TargetRange[1]:
|
|
||||||
# Thread = UploadThread(baseArr)
|
|
||||||
# Thread.start()
|
|
||||||
# baseArr += 1
|
|
||||||
|
|
||||||
|
elif type == 3:
|
||||||
|
while baseArr <= TargetRange[1]:
|
||||||
|
Thread = UploadThread(baseArr)
|
||||||
|
Thread.start()
|
||||||
|
baseArr += 1
|
||||||
|
Thread = UploadThread(baseArr)
|
||||||
|
Thread.start()
|
||||||
|
baseArr += 1
|
||||||
|
Thread = UploadThread(baseArr)
|
||||||
|
Thread.start()
|
||||||
|
baseArr += 1
|
||||||
|
|||||||
Reference in New Issue
Block a user