Files
getDomain/domainCheck/app/core/domain_collector.py
2026-04-16 13:33:06 +08:00

261 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: UTF-8 -*-
'''
@Project :domainScanDemo
@File :domain_collector.py
@IDE :PyCharm
@Author :梦伴
@Date :2026/4/8 23:50
@explain : 域名收集器
'''
import re
import tldextract
from loguru import logger
from app.utils.database import Database
from app.utils.domain_utils import normalize_domain
from app.config import config
class DomainCollector:
"""
域名收集器
"""
def __init__(self):
"""
初始化域名收集器
"""
self.db = Database(
host=config.DB_HOST,
port=config.DB_PORT,
database=config.DB_DATABASE,
user=config.DB_USER,
password=config.DB_PASSWORD
)
def add_domain(self, domain, source_type):
"""
添加域名
:param domain: 域名
:param source_type: 来源类型
:return: bool - 是否添加成功
"""
try:
# 标准化域名
normalized_domain = normalize_domain(domain)
if not normalized_domain:
logger.warning(f"无效域名: {domain}")
return False
# 提取顶级域名
ext = tldextract.extract(normalized_domain)
tld = ext.suffix
# 只保留 .com 和 .net
if tld not in ['com', 'net']:
logger.warning(f"不支持的顶级域名: {tld}")
return False
# 检查是否已存在
if self.db.domain_exists(normalized_domain):
logger.info(f"域名已存在: {normalized_domain}")
return False
# 添加域名
domain_id = self.db.add_domain(normalized_domain, tld, source_type)
if domain_id:
# 创建检测任务
self.db.create_detect_task(domain_id, 1) # 1 表示基础检测
logger.info(f"成功添加域名: {normalized_domain}")
return True
else:
logger.error(f"添加域名失败: {normalized_domain}")
return False
except Exception as e:
logger.error(f"添加域名出错: {e}")
return False
def add_domains_batch(self, domains, source_type, batch_size=1000, dry_run=False):
"""
批量添加域名
:param domains: 域名列表
:param source_type: 来源类型
:param batch_size: 批量大小
:param dry_run: 是否仅进行干运行(不实际添加域名)
:return: dict - 统计信息
"""
try:
# 统计信息
stats = {
'total': len(domains),
'valid': 0,
'added': 0,
'exists': 0,
'invalid': 0,
'failed': 0
}
# 处理大规模数据时,分批进行标准化和过滤
normalized_domains = []
batch_domains = []
for i, domain in enumerate(domains):
normalized = normalize_domain(domain)
if not normalized:
stats['invalid'] += 1
continue
# 提取顶级域名
ext = tldextract.extract(normalized)
tld = ext.suffix
# 只保留 .com 和 .net
if tld not in ['com', 'net']:
stats['invalid'] += 1
continue
normalized_domains.append((normalized, tld))
batch_domains.append(normalized)
stats['valid'] += 1
# 每1000个域名检查一次避免内存占用过高
if (i + 1) % 1000 == 0:
logger.info(f"已处理 {i + 1}/{len(domains)} 个域名")
logger.info(f"域名标准化完成,有效域名: {stats['valid']}")
# 提取所有域名
all_domains = [domain for domain, tld in normalized_domains]
# 批量检查域名是否存在
existing_domains = self.db.check_domains_exist(all_domains)
existing_set = set(existing_domains)
# 准备批量添加数据
batch_data = []
for domain, tld in normalized_domains:
if domain not in existing_set:
batch_data.append((domain, tld, source_type))
stats['exists'] = len(existing_domains)
stats['valid'] = len(normalized_domains)
# 干运行模式下直接返回统计信息
if dry_run:
stats['added'] = len(batch_data)
logger.info(f"干运行模式:准备添加 {len(batch_data)} 个新域名")
return stats
logger.info(f"准备添加 {len(batch_data)} 个新域名")
# 分批次添加
for i in range(0, len(batch_data), batch_size):
batch = batch_data[i:i+batch_size]
added_count = self.db.add_domains_batch(batch)
stats['added'] += added_count
stats['failed'] += len(batch) - added_count
# 每处理一批,记录一次进度
if (i + len(batch)) % (batch_size * 10) == 0:
logger.info(f"已添加 {i + len(batch)}/{len(batch_data)} 个域名")
logger.info(f"批量添加域名完成: {stats}")
return stats
except Exception as e:
logger.error(f"批量添加域名出错: {e}")
return {
'total': len(domains),
'valid': 0,
'added': 0,
'exists': 0,
'invalid': 0,
'failed': len(domains)
}
def import_from_file(self, file_path, source_type, batch_size=1000):
"""
从文件导入域名
:param file_path: 文件路径
:param source_type: 来源类型
:param batch_size: 批量大小
:return: dict - 导入统计信息
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
domains = f.readlines()
# 提取域名
domain_list = []
for domain in domains:
domain = domain.strip()
if domain:
domain_list.append(domain)
# 批量添加域名
stats = self.add_domains_batch(domain_list, source_type, batch_size)
logger.info(f"从文件导入完成: {stats}")
return stats
except Exception as e:
logger.error(f"从文件导入出错: {e}")
return {
'total': 0,
'valid': 0,
'added': 0,
'exists': 0,
'invalid': 0,
'failed': 0
}
def collect_from_juming(self, type_='一口价'):
"""
从聚名网收集域名
:param type_: 类型,一口价或过期删除
:return: int - 收集到的域名数量
"""
# 这里可以添加从聚名网收集域名的逻辑
logger.info(f"从聚名网收集 {type_} 域名")
# 模拟收集结果
return 0
def collect_from_search_engine(self, keyword, limit=100):
"""
从搜索引擎收集域名
:param keyword: 关键词
:param limit: 限制数量
:return: int - 收集到的域名数量
"""
# 这里可以添加从搜索引擎收集域名的逻辑
logger.info(f"从搜索引擎收集域名,关键词: {keyword}, 限制: {limit}")
# 模拟收集结果
return 0
def collect_from_enterprise_directory(self, url, limit=100):
"""
从企业目录收集域名
:param url: 企业目录URL
:param limit: 限制数量
:return: int - 收集到的域名数量
"""
# 这里可以添加从企业目录收集域名的逻辑
logger.info(f"从企业目录收集域名URL: {url}, 限制: {limit}")
# 模拟收集结果
return 0
def collect_from_zone_file(self, file_path):
"""
从Zone File收集域名
:param file_path: Zone File路径
:return: int - 收集到的域名数量
"""
# 这里可以添加从Zone File收集域名的逻辑
logger.info(f"从Zone File收集域名文件: {file_path}")
# 模拟收集结果
return 0