first commit
This commit is contained in:
4
app/utils/__init__.py
Normal file
4
app/utils/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
'''
|
||||
工具类模块
|
||||
'''
|
||||
BIN
app/utils/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
app/utils/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/utils/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
app/utils/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/utils/__pycache__/database.cpython-311.pyc
Normal file
BIN
app/utils/__pycache__/database.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/utils/__pycache__/database.cpython-39.pyc
Normal file
BIN
app/utils/__pycache__/database.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/utils/__pycache__/domain_utils.cpython-311.pyc
Normal file
BIN
app/utils/__pycache__/domain_utils.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/utils/__pycache__/domain_utils.cpython-39.pyc
Normal file
BIN
app/utils/__pycache__/domain_utils.cpython-39.pyc
Normal file
Binary file not shown.
1362
app/utils/database.py
Normal file
1362
app/utils/database.py
Normal file
File diff suppressed because it is too large
Load Diff
223
app/utils/domain_utils.py
Normal file
223
app/utils/domain_utils.py
Normal file
@@ -0,0 +1,223 @@
|
||||
# -*- 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
|
||||
|
||||
|
||||
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 - 状态描述
|
||||
"""
|
||||
status_map = {
|
||||
0: '待检测',
|
||||
1: '可注册',
|
||||
2: '已注册',
|
||||
3: '宽限期',
|
||||
4: '赎回期',
|
||||
5: '删除期',
|
||||
6: 'clientHold',
|
||||
7: 'serverHold',
|
||||
8: '状态未知',
|
||||
9: '检测失败'
|
||||
}
|
||||
|
||||
return status_map.get(status_code, '未知')
|
||||
|
||||
|
||||
def parse_use_status(status_code):
|
||||
"""
|
||||
解析使用状态码
|
||||
|
||||
:param status_code: 状态码
|
||||
:return: str - 状态描述
|
||||
"""
|
||||
status_map = {
|
||||
0: '未使用',
|
||||
1: '已经使用',
|
||||
2: '已经卖出',
|
||||
3: '已经预定'
|
||||
}
|
||||
|
||||
return status_map.get(status_code, '未知')
|
||||
|
||||
|
||||
def parse_detect_status(status_code):
|
||||
"""
|
||||
解析检测状态码
|
||||
|
||||
:param status_code: 状态码
|
||||
:return: str - 状态描述
|
||||
"""
|
||||
status_map = {
|
||||
0: '待检测',
|
||||
1: '检测中',
|
||||
2: '正常',
|
||||
3: '黑名单',
|
||||
4: '检测失败',
|
||||
5: '暂停检测'
|
||||
}
|
||||
|
||||
return status_map.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, '未知')
|
||||
157
app/utils/http_utils.py
Normal file
157
app/utils/http_utils.py
Normal 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
|
||||
Reference in New Issue
Block a user