如何在Python中可靠检测任意TLD域名的注册状态?
可靠检测任意TLD域名注册状态的Python方案
我完全懂你这个痛点——要覆盖所有TLD还得保证检测可靠性,确实是个挺棘手的问题。你试过的几个方案都踩了典型的坑,下面结合这些问题给你一套综合优化的思路:
一、先梳理现有方案的核心问题
你提到的尝试都戳中了这类需求的常见瓶颈:
python-whois/whois库:硬编码支持的TLD有限,对.run这类新通用TLD(gTLD)覆盖不足,维护速度跟不上TLD的新增节奏;- 调用系统
whois命令:兼容性比第三方库好,但共享IP下很容易触发WHOIS服务器的频率限制,而且不同操作系统的whois命令行为还可能有差异; - DNS查询:只能检测有解析记录的域名,完全覆盖不了已注册但未配置DNS、处于赎回期/删除期的域名;
- 第三方API:隐私风险是硬伤,尤其是查询潜在优质域名时,很容易被恶意平台盯上抢注。
二、综合优化方案:自定义WHOIS查询+多维度验证+反限制策略
1. 直接对接对应TLD的官方WHOIS服务器
系统whois命令本质也是对接对应TLD的服务器,但我们自己实现这个逻辑,能更灵活地支持所有TLD:
- 第一步:通过IANA的WHOIS服务器获取目标域名TLD的官方WHOIS地址:
import subprocess def get_tld_whois_server(tld): # 从IANA查询TLD对应的官方WHOIS服务器 try: result = subprocess.run( ['whois', '-h', 'whois.iana.org', tld], capture_output=True, text=True, timeout=10 ) for line in result.stdout.split('\n'): if 'whois:' in line.lower(): return line.split(':')[1].strip() except Exception as e: print(f"获取{TLD}的WHOIS服务器失败:{str(e)}") return None - 第二步:直接对接该服务器查询域名,绕开系统
whois的中间层限制:def query_whois(domain, whois_server): try: result = subprocess.run( ['whois', '-h', whois_server, domain], capture_output=True, text=True, timeout=10 ) return result.stdout except Exception as e: return f"查询{whois_server}出错:{str(e)}"
2. 通用化WHOIS结果解析
不同TLD的WHOIS返回格式差异极大,我们可以通过关键词匹配来统一判断注册状态:
def is_domain_available(whois_output): # 整理各TLD通用的"域名可用"关键词 available_keywords = [ "no match for", "not found", "available", "is free", "status: available", "domain not registered", "no object found" ] # 整理各TLD通用的"域名已注册"关键词 registered_keywords = [ "domain name:", "registrar:", "creation date:", "status: active", "registered on:", "expiry date:" ] lower_output = whois_output.lower() # 优先判断是否可用 for keyword in available_keywords: if keyword in lower_output: return True # 再判断是否已注册 for keyword in registered_keywords: if keyword in lower_output: return False # 无法明确判断的情况(比如返回异常、格式特殊) return None
3. 解决IP限制问题
- 添加随机请求延迟:每次查询后随机等待1-3秒,避免短时间内大量请求触发限制:
import time import random time.sleep(random.uniform(1, 3)) - 使用代理池轮询:如果是批量查询,搭配代理IP轮换(比如用
socks库或requests的代理功能),避免单IP被封禁。
4. 多维度交叉验证
为了进一步提升可靠性,可以结合两种方式验证:
- 先做DNS A/AAAA记录查询(用
dnspython库),如果有记录直接判定已注册; - 对DNS无记录的域名,再用WHOIS查询验证,避免漏掉已注册但未配置DNS的情况;
- 对WHOIS返回模糊的域名,可以补充查询TLD注册局的公开无隐私风险接口(部分注册局提供这类服务)。
三、完整流程示例
import subprocess import time import random import dns.resolver def get_tld_whois_server(tld): try: result = subprocess.run( ['whois', '-h', 'whois.iana.org', tld], capture_output=True, text=True, timeout=10 ) for line in result.stdout.split('\n'): if 'whois:' in line.lower(): return line.split(':')[1].strip() except Exception as e: print(f"获取.{tld}的WHOIS服务器失败:{str(e)}") return None def query_whois(domain, whois_server): try: result = subprocess.run( ['whois', '-h', whois_server, domain], capture_output=True, text=True, timeout=10 ) return result.stdout except Exception as e: return f"查询出错:{str(e)}" def check_dns_record(domain): try: resolver = dns.resolver.Resolver() resolver.timeout = 5 resolver.lifetime = 5 # 查询A记录 resolver.resolve(domain, 'A') return True except (dns.resolver.NXDOMAIN, dns.exception.Timeout, dns.resolver.NoAnswer): return False except Exception as e: print(f"DNS查询出错:{str(e)}") return None def is_domain_available(whois_output): available_keywords = [ "no match for", "not found", "available", "is free", "status: available", "domain not registered", "no object found" ] registered_keywords = [ "domain name:", "registrar:", "creation date:", "status: active", "registered on:", "expiry date:" ] lower_output = whois_output.lower() for kw in available_keywords: if kw in lower_output: return True for kw in registered_keywords: if kw in lower_output: return False return None def check_domain_status(domain): # 第一步:DNS快速判断 dns_result = check_dns_record(domain) if dns_result is True: print(f"域名 {domain} 已注册(检测到DNS记录)") return False elif dns_result is None: print(f"{domain} 的DNS查询失败,切换到WHOIS查询") # 第二步:获取TLD的WHOIS服务器 tld = domain.split('.')[-1] whois_server = get_tld_whois_server(tld) if not whois_server: print(f"无法获取.{tld}的WHOIS服务器") return None # 添加随机延迟避免限制 time.sleep(random.uniform(1, 3)) # 第三步:WHOIS查询并解析 whois_output = query_whois(domain, whois_server) available = is_domain_available(whois_output) if available is True: print(f"域名 {domain} 可用") elif available is False: print(f"域名 {domain} 已注册(检测到WHOIS记录)") else: print(f"无法判定{domain}的状态,原始WHOIS输出:\n{whois_output}") return available # 测试示例 check_domain_status("example.run") check_domain_status("example.com")
四、注意事项
- 部分TLD的WHOIS服务器需要特殊查询格式(比如
.cn),可以针对这类特殊TLD单独做逻辑适配; - 对于处于赎回期/删除期的域名,WHOIS会返回
pendingDelete这类特殊状态,这类域名虽显示已注册,但短期内会释放,需要额外判断; - 哪怕加了延迟和代理,也不要高频批量查询,避免触发注册局的严格限制。
内容的提问来源于stack exchange,提问作者tmt
相关产品推荐
相关产品推荐

