完善功能

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
我超,盒
# 我超,盒
#
### 本项目通过使用 {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
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}')
exit_flag = True
clean_image()
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
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}')
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 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<TargetRange[1]:
# Thread = ByNetFindThread(TargetImageHash, baseArr)
# Thread.start()
# baseArr += 1
# while baseArr<=TargetRange[1]:
# Thread = UploadThread(baseArr)
# Thread.start()
# baseArr += 1
elif type == 2:
while baseArr < TargetRange[1]:
Thread = ByNetFindThread(TargetImageHash, 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