convert domainCheck to regular directory

This commit is contained in:
Your Name
2026-04-16 13:33:06 +08:00
parent e406d73334
commit d37c444929
107 changed files with 254185 additions and 1 deletions

View File

@@ -0,0 +1,4 @@
# -*- coding: UTF-8 -*-
'''
工具类模块
'''

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,195 @@
# -*- coding: UTF-8 -*-
'''
@Project :domainScanDemo
@File :domain_utils.py
@IDE :PyCharm
@Author :梦伴
@Date :2026/4/9 0:05
@explain : 域名工具类
'''
import re
import tldextract
from loguru import logger
from app.utils.status_codes import DETECT_STATUS_LABELS, REGISTER_STATUS_LABELS, USE_STATUS_LABELS
def normalize_domain(domain):
"""
标准化域名
:param domain: 域名
:return: str - 标准化后的域名
"""
try:
# 转换为小写
domain = domain.lower()
# 去除空格
domain = domain.strip()
# 去除协议
domain = re.sub(r'^https?://', '', domain)
# 去除路径和查询参数
domain = domain.split('/')[0]
domain = domain.split('?')[0]
# 去除端口
domain = domain.split(':')[0]
# 只保留主域
ext = tldextract.extract(domain)
if ext.domain and ext.suffix:
domain = f"{ext.domain}.{ext.suffix}"
# 验证域名格式
if not is_valid_domain(domain):
return None
return domain
except Exception as e:
logger.error(f"标准化域名出错: {e}")
return None
def is_valid_domain(domain):
"""
验证域名格式
:param domain: 域名
:return: bool - 是否有效
"""
try:
# 域名格式正则
pattern = r'^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, domain))
except Exception as e:
logger.error(f"验证域名格式出错: {e}")
return False
def extract_tld(domain):
"""
提取顶级域名
:param domain: 域名
:return: str - 顶级域名
"""
try:
ext = tldextract.extract(domain)
return ext.suffix
except Exception as e:
logger.error(f"提取顶级域名出错: {e}")
return ''
def extract_domain(domain):
"""
提取主域名
:param domain: 域名
:return: str - 主域名
"""
try:
ext = tldextract.extract(domain)
if ext.domain and ext.suffix:
return f"{ext.domain}.{ext.suffix}"
return domain
except Exception as e:
logger.error(f"提取主域名出错: {e}")
return domain
def is_com_or_net(domain):
"""
检查是否为 .com 或 .net 域名
:param domain: 域名
:return: bool - 是否为 .com 或 .net 域名
"""
try:
tld = extract_tld(domain)
return tld in ['com', 'net']
except Exception as e:
logger.error(f"检查域名后缀出错: {e}")
return False
def generate_domain_variants(domain):
"""
生成域名变体
:param domain: 域名
:return: list - 域名变体列表
"""
try:
variants = []
# 原始域名
variants.append(domain)
# 添加 www
if not domain.startswith('www.'):
variants.append(f"www.{domain}")
# 移除 www
if domain.startswith('www.'):
variants.append(domain[4:])
return variants
except Exception as e:
logger.error(f"生成域名变体出错: {e}")
return [domain]
def parse_domain_status(status_code):
"""
解析域名状态码
:param status_code: 状态码
:return: str - 状态描述
"""
return REGISTER_STATUS_LABELS.get(status_code, '未知')
def parse_use_status(status_code):
"""
解析使用状态码
:param status_code: 状态码
:return: str - 状态描述
"""
return USE_STATUS_LABELS.get(status_code, '未知')
def parse_detect_status(status_code):
"""
解析检测状态码
:param status_code: 状态码
:return: str - 状态描述
"""
return DETECT_STATUS_LABELS.get(status_code, '未知')
def parse_source_type(source_type):
"""
解析来源类型
:param source_type: 来源类型
:return: str - 来源描述
"""
source_map = {
1: '聚名一口价',
2: '聚名过期删除',
3: 'zone file',
4: '搜索引擎采集',
5: '企业目录采集',
6: '手工录入',
7: 'TXT 导入',
8: '第三方接口',
9: '其它'
}
return source_map.get(source_type, '未知')

View File

@@ -0,0 +1,157 @@
# -*- coding: UTF-8 -*-
'''
@Project :domainScanDemo
@File :http_utils.py
@IDE :PyCharm
@Author :梦伴
@Date :2026/4/9 0:06
@explain : HTTP工具类
'''
import requests
from curl_cffi import requests as curl_requests
from loguru import logger
class HTTPUtils:
"""
HTTP工具类
"""
@staticmethod
def get(url, headers=None, params=None, timeout=10, proxies=None, use_curl=False):
"""
发送GET请求
:param url: 请求URL
:param headers: 请求头
:param params: 查询参数
:param timeout: 超时时间
:param proxies: 代理
:param use_curl: 是否使用curl_cffi
:return: requests.Response - 响应对象
"""
try:
if use_curl:
# 使用curl_cffi模拟浏览器
response = curl_requests.get(url, headers=headers, params=params, timeout=timeout, proxies=proxies, impersonate='chrome')
else:
# 使用requests
response = requests.get(url, headers=headers, params=params, timeout=timeout, proxies=proxies)
response.raise_for_status() # 检查状态码
return response
except Exception as e:
logger.error(f"GET请求失败: {url}, 错误: {e}")
return None
@staticmethod
def post(url, headers=None, data=None, json=None, timeout=10, proxies=None, use_curl=False):
"""
发送POST请求
:param url: 请求URL
:param headers: 请求头
:param data: 表单数据
:param json: JSON数据
:param timeout: 超时时间
:param proxies: 代理
:param use_curl: 是否使用curl_cffi
:return: requests.Response - 响应对象
"""
try:
if use_curl:
# 使用curl_cffi模拟浏览器
response = curl_requests.post(url, headers=headers, data=data, json=json, timeout=timeout, proxies=proxies, impersonate='chrome')
else:
# 使用requests
response = requests.post(url, headers=headers, data=data, json=json, timeout=timeout, proxies=proxies)
response.raise_for_status() # 检查状态码
return response
except Exception as e:
logger.error(f"POST请求失败: {url}, 错误: {e}")
return None
@staticmethod
def get_random_user_agent():
"""
获取随机用户代理
:return: str - 用户代理
"""
user_agents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/138.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/146.0.0.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15'
]
import random
return random.choice(user_agents)
@staticmethod
def get_default_headers():
"""
获取默认请求头
:return: dict - 请求头
"""
return {
'User-Agent': HTTPUtils.get_random_user_agent(),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1'
}
@staticmethod
def retry_request(func, max_retries=3, delay=1):
"""
重试请求
:param func: 请求函数
:param max_retries: 最大重试次数
:param delay: 重试延迟
:return: 函数返回值
"""
import time
for i in range(max_retries):
try:
result = func()
if result:
return result
except Exception as e:
logger.warning(f"请求失败,第 {i+1} 次重试: {e}")
if i < max_retries - 1:
time.sleep(delay)
return None
@staticmethod
def check_proxy(proxy):
"""
检查代理是否可用
:param proxy: 代理URL
:return: bool - 是否可用
"""
try:
proxies = {
'http': proxy,
'https': proxy
}
response = requests.get('https://www.baidu.com', proxies=proxies, timeout=5)
return response.status_code == 200
except Exception as e:
logger.error(f"代理检查失败: {proxy}, 错误: {e}")
return False

View File

@@ -0,0 +1,66 @@
"""Centralized status codes and labels used across detection, database and UI."""
REGISTER_STATUS_PENDING = 0
REGISTER_STATUS_AVAILABLE = 2
REGISTER_STATUS_REGISTERED = 3
REGISTER_STATUS_GRACE = 4
REGISTER_STATUS_REDEMPTION = 5
REGISTER_STATUS_PENDING_DELETE = 6
REGISTER_STATUS_CLIENT_HOLD = 7
REGISTER_STATUS_SERVER_HOLD = 8
REGISTER_STATUS_UNKNOWN = 9
REGISTER_STATUS_FAILED = 10
DETECT_STATUS_PENDING = 0
DETECT_STATUS_COMPLETED = 1
DETECT_STATUS_RUNNING = 2
DETECT_STATUS_BLACKLISTED = 3
DETECT_STATUS_FAILED = 4
USE_STATUS_UNUSED = 0
USE_STATUS_USED = 1
USE_STATUS_SOLD = 2
USE_STATUS_RESERVED = 3
REVIEW_STATUS_NONE = 0
REVIEW_STATUS_PENDING = 1
REVIEW_STATUS_APPROVED = 2
REVIEW_STATUS_REJECTED = 3
THIRD_PARTY_STATUS_PENDING = 0
THIRD_PARTY_STATUS_DONE = 1
REGISTER_STATUS_LABELS = {
REGISTER_STATUS_PENDING: '待检测',
REGISTER_STATUS_AVAILABLE: '可注册',
REGISTER_STATUS_REGISTERED: '已注册',
REGISTER_STATUS_GRACE: '宽限期',
REGISTER_STATUS_REDEMPTION: '赎回期',
REGISTER_STATUS_PENDING_DELETE: '删除期',
REGISTER_STATUS_CLIENT_HOLD: 'clientHold',
REGISTER_STATUS_SERVER_HOLD: 'serverHold',
REGISTER_STATUS_UNKNOWN: '状态未知',
REGISTER_STATUS_FAILED: '检测失败',
}
DETECT_STATUS_LABELS = {
DETECT_STATUS_PENDING: '待检测',
DETECT_STATUS_COMPLETED: '检测完成',
DETECT_STATUS_RUNNING: '检测中',
DETECT_STATUS_BLACKLISTED: '黑名单',
DETECT_STATUS_FAILED: '检测失败',
}
USE_STATUS_LABELS = {
USE_STATUS_UNUSED: '未使用',
USE_STATUS_USED: '已经使用',
USE_STATUS_SOLD: '已经卖出',
USE_STATUS_RESERVED: '已经预定',
}
REVIEW_STATUS_LABELS = {
REVIEW_STATUS_NONE: '无需复核',
REVIEW_STATUS_PENDING: '待人工复核',
REVIEW_STATUS_APPROVED: '人工通过',
REVIEW_STATUS_REJECTED: '人工拒绝',
}