From 1d534be4c1622dd5debcaad2c652c647365d14ac Mon Sep 17 00:00:00 2001 From: Qiea <1310371422@qq.com> Date: Sun, 22 Dec 2024 11:06:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 21 ++++++++++++++- Thread.py | 64 +++++++++++++++++++++----------------------- tools.py => Tools.py | 47 ++++++++++++++++++++++++-------- config.cfg | 22 +++++++++++++++ main.py | 43 ++++++++++++++++++----------- 5 files changed, 136 insertions(+), 61 deletions(-) rename tools.py => Tools.py (65%) create mode 100644 config.cfg diff --git a/README.md b/README.md index 2735454..e831f1a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,21 @@ # 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 \ No newline at end of file diff --git a/Thread.py b/Thread.py index b4a0f38..562f4ec 100644 --- a/Thread.py +++ b/Thread.py @@ -1,55 +1,46 @@ -import threading -import pymysql -from tools import * +import pymysql, threading +from Tools import config, download_image, Hash, remove_image, compare, Image, imagehash, os, logging, clean_image +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): def __init__(self, uploadqqnumber): super().__init__() self.uploadqqnumber = uploadqqnumber - self.conn = pymysql.connect( - host='192.168.9.1', # 你的 MySQL 主机 - user='root', # 你的 MySQL 用户 - password='123456', # 你的 MySQL 密码 - database='qqinfo' # 你要连接的数据库 - ) - - - def conn_close(self): - self.conn.close() + self.conn = Myconn def run(self): - print(f'我是上传线程{self.uploadqqnumber}') + logging.debug(f'我是上传线程{self.uploadqqnumber}') if download_image(self.uploadqqnumber): Hash(self.conn).tomysql(self.uploadqqnumber) - print('上传成功') + logging.info(f'上传成功: {self.uploadqqnumber}') remove_image(self.uploadqqnumber) - + self.conn.close() class FindThread(threading.Thread): def __init__(self, TargetImageHash): super().__init__() self.TargetImageHash = TargetImageHash - self.conn = pymysql.connect( - host='192.168.9.1', # 你的 MySQL 主机 - user='root', # 你的 MySQL 用户 - password='123456', # 你的 MySQL 密码 - database='qqinfo' # 你要连接的数据库 - ) - - - def conn_close(self): - self.conn.close() + self.conn = Myconn def run(self): - print(f'我是查询线程{self.TargetImageHash}') + global exit_flag + logging.debug(f'我是查询线程{self.TargetImageHash}') res = Hash(self.conn).getqq(self.TargetImageHash) if res != 'error': - print(f'查询成功,QQ号是: {res}') - exit() + logging.info(f'查询成功,QQ号是: {res}') + exit_flag = True + self.conn.close() @@ -61,13 +52,20 @@ class ByNetFindThread(threading.Thread): def run(self): + global exit_flag if download_image(self.findqqnumber): 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))) res = compare(self.TargetImageHash, FindImageHash) 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') - exit() - print(f'[{self.findqqnumber}]的相似度是:{res}') - remove_image(self.findqqnumber) \ No newline at end of file + exit_flag = True + clean_image() + os._exit(0) + logging.info(f'[{self.findqqnumber}]的相似度是:{res}%') + remove_image(self.findqqnumber) diff --git a/tools.py b/Tools.py similarity index 65% rename from tools.py rename to Tools.py index d444730..89f020b 100644 --- a/tools.py +++ b/Tools.py @@ -1,8 +1,14 @@ -import os -import requests 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: def __init__(self, conn): @@ -19,9 +25,9 @@ class Hash: _cursor.execute('SELECT hash FROM image_hashes WHERE id = (%s)', (_qqnumber,)) byte_data_from_db = _cursor.fetchone() if byte_data_from_db is None: - print(f'{_qqnumber}不在数据库内') + logging.info(f'{_qqnumber}不在数据库内') else: - print(f'从数据库获取的Hash号: {byte_data_from_db[0]}') + logging.debug(f'从数据库获取的Hash号: {byte_data_from_db[0]}') _cursor.close() return byte_data_from_db[0] @@ -36,10 +42,10 @@ class Hash: _cursor.execute('SELECT id FROM image_hashes WHERE hash = (%s)', (_hash,)) byte_data_from_db = _cursor.fetchone() if byte_data_from_db is None: - print('Hash值不存在') + logging.info('Hash值不存在') return 'error' else: - print(f'从数据库获取的QQ号: {byte_data_from_db[0]}') + logging.debug(f'从数据库获取的QQ号: {byte_data_from_db[0]}') _cursor.close() return byte_data_from_db[0] @@ -50,6 +56,8 @@ class Hash: :param: _qqnumber: QQ号 """ _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))) _cursor = self.conn.cursor() _cursor.execute(""" @@ -58,7 +66,7 @@ class Hash: ON DUPLICATE KEY UPDATE hash = VALUES(hash) """, (_qqnumber, _byte_data)) - print(f'[{_qqnumber}]:{_byte_data}') + logging.debug(f'[{_qqnumber}]:{_byte_data}') self.conn.commit() _cursor.close() @@ -106,10 +114,10 @@ def download_image(_qqnumber): # 保存图片 with open(image_name, 'wb') as f: f.write(response.content) - print(f'图片已保存为 {image_name}') + logging.debug(f'图片已保存为 {image_name}') return 1 else: - print(f'下载图片失败,错误码:{response.status_code}') + logging.info(f'下载图片失败,错误码:{response.status_code}') return 0 @@ -124,4 +132,21 @@ def remove_image(_qqnumber): os.remove(f'./img/{_qqnumber}.jpg') return 1 else: - print(f'没有找到这个QQ号的图片:{_qqnumber}') \ No newline at end of file + 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}") \ No newline at end of file diff --git a/config.cfg b/config.cfg new file mode 100644 index 0000000..64c1bb9 --- /dev/null +++ b/config.cfg @@ -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 \ No newline at end of file diff --git a/main.py b/main.py index d06592a..1853069 100644 --- a/main.py +++ b/main.py @@ -1,24 +1,35 @@ -from Thread import pymysql, UploadThread, FindThread, ByNetFindThread , threading -from tools import imagehash, Image, download_image +from Thread import UploadThread, FindThread, ByNetFindThread +from Tools import imagehash, Image, os, config -# download_image(1310371422) -TargetRange = [1310372220, 1310372400] -TargetImage = Image.open(str(f'./img/target3.jpg')) +type = int(config['settings']['type']) +TargetRange = list(map(int, config['settings']['TargetRange'].split(','))) +TargetImagePath = config['settings']['TargetImage'] +TargetImage = Image.open(TargetImagePath) TargetImageHash = bytes.fromhex(str(imagehash.average_hash(TargetImage))) baseArr = TargetRange[0] +if not os.path.exists('img'): + os.makedirs('img') if __name__ == '__main__': - Thread = FindThread(TargetImageHash) - Thread.start() + if type == 1: + Thread = FindThread(TargetImageHash) + Thread.start() - # while baseArr