完善功能

This commit is contained in:
Qiea
2024-12-22 11:06:55 +08:00
parent 451ac8ec83
commit 1d534be4c1
5 changed files with 136 additions and 61 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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
View 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
View File

@@ -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