十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用Python打造一站式域名查询系统:WHOIS、DNS与主机状态批量检测

用Python打造一站式域名查询系统:WHOIS、DNS与主机状态批量检测 简介一套基于PHP的易捷域名查询系统v1.0源码面向个人站长、域名投资者及网络运维人员用于快速搭建轻量级域名注册状态、可用性与管理信息查询工具。压缩包内只有1个php文件包体约2KB部署非常轻便可在虚拟主机或本地PHP环境中直接运行无需额外依赖。功能上围绕域名Whois核心逻辑展开涵盖实时状态查询、多后缀支持、智能域名建议、批量查询、历史注册信息与安全检测等维度支持国际及国内主流后缀虽为单文件却结构清晰适合二次开发或学习PHP与域名服务交互。目前已有169人学习下载尤其适合希望理解域名查询实现原理、掌握简易后台管理思路的初学者。读者可从中获得可运行的查询脚本参考学习PHP发送网络请求、解析返回数据、设计简明交互界面的完整路径并可根据自身需求延伸至DNS配置、续费提醒或服务器托管等场景是理解完整域名查询流程的实用范例。 主机域名查询这件事我做这个“易捷域名查询系统v1.0”英文名 ej99domain完全是被逼出来的。有段时间经常帮朋友看域名能不能注册、什么时候到期、解析有没有出问题每次都要打开好几个网页来回切先去注册商后台查WHOIS再去第三方平台看DNS解析还要手动 ping 一下主机通不通。域名多了以后效率低到让人崩溃。后来我干脆自己写了一个查询系统把这些操作全部整合到一个页面里输入域名就能批量返回注册信息、到期时间、DNS 记录和主机存活状态。这篇文章就把整个项目的设计思路、核心实现和踩过的坑完整分享一下适合正在做运维工具、域名资产管理或者想学 Python 网络编程的开发者参考。1. 项目缘起与整体设计思路1.1 最初的使用场景这个问题的起点其实非常小我有一次需要统计 30 多个域名的续费时间逐个登录注册商后台实在太痛苦而第三方 WHOIS 网站虽然能查但一次只能查一个而且页面里全是广告。更麻烦的是光知道到期时间还不够还要同时看这些域名的 DNS 解析有没有被改动、CDN 有没有失效、主机是不是已经挂掉。实际查一圈下来30 个域名至少要花费一两个小时。所以我的目标很清楚做一个内部小工具输入一批域名之后能在十几秒内把所有基础信息拉回来。这个需求听起来简单真做起来坑不少。不同域名后缀的 WHOIS 服务器不一样返回的文本格式也五花八门DNS 解析要区分 A 记录、CNAME、MX、NS 多种类型主机状态检测又涉及端口连通性。把这些链路串起来之后系统的复杂度一下子就上来了。1.2 模块化设计拆解查询链路我把整个系统划分成几个相对独立的模块这样后续维护和扩展会轻松很多。域名解析模块负责把域名解析成 IP并提取 A、CNAME、MX、NS 等记录用于判断解析状态和机房归属。WHOIS 信息模块负责发起 WHOIS 查询解析注册商、注册时间、到期时间、DNS 服务器等关键字段。主机状态模块负责检测 IP 或域名的端口连通情况判断服务器是否存活。批量调度模块接收一批域名调度上面三个模块并行处理汇总结果。展示与导出模块提供简单的 Web 界面支持表格展示也能一键导出 CSV 或 TXT。为什么用 Python 而不是其他语言一是 Python 的网络生态非常成熟dnspython、python-whois这类库可以直接调用不用自己从头解析底层协议二是开发速度快一个 Flask 应用加上几个工具类一个晚上就能跑通核心逻辑。对于这种内部工具来说快速出活比追求极致的性能更重要。2. 核心功能拆解每个查询背后在做什么2.1 WHOIS 查询注册信息与到期时间WHOIS 本质上是一个跑在 TCP 43 端口上的查询服务。客户端把要查询的域名作为一行文本发送给 WHOIS 服务器服务器返回一段人类可读的文本信息。不同后缀对应的 WHOIS 服务器不同比如.com和.net走 Verisign 的服务器.org走 PIR 的服务器.cn则要去 CNNIC 查询。我一开始直接用了python-whois这个库它最大的优势是已经内置了各后缀对应的服务器列表还会拿正则表达式去解析返回文本。但实测下来发现几个问题部分后缀的返回格式更新后这个库的解析规则没有跟上需要手动打补丁。隐私保护开启后注册人信息是一堆代理数据解析出来也没有实际意义。有些小型注册商的 WHOIS 服务器响应很慢容易超时。所以后来我在库的基础上增加了一层自定义解析逻辑用多个正则规则依次匹配匹配不到就直接展示原始文本。这样至少不会因为某一个字段格式异常导致整体查询失败。这里有个很实用的细节python-whois在查询时会把网站自带的whois命令当作兜底但生产环境不一定有系统命令的权限。我直接绕过了它强制走内置的whois模块这样部署在容器里也不会出问题。2.2 DNS 解析不止是查 A 记录很多人对 DNS 的理解就是“域名转 IP”但实际做域名管理的时候需要关注的记录类型至少包括这么几种记录类型含义使用场景A / AAAA主机地址记录判断服务器 IP 指向CNAME别名记录看看域名是不是指向某个别名MX邮件路由记录邮箱服务是否正常NS权威域名服务器看看托管商是否变更TXT任意文本记录SPF、DKIM、验证文件常见实现上我使用dnspython库做递归解析。有一个很容易踩的坑本地启用了 DNS 缓存或者使用了公共 DNS 后解析结果不一定能反映真实生效情况。所以我的系统里做了一个“权威 DNS 直查”的选项直接向域名的 NS 服务器发起查询绕过本地缓存这样拿到的才是真正在权威侧生效的记录。实际使用中还会遇到一种很坑的情况某些国际域名在国内访问时解析被污染导致 A 记录指向错误。这个问题靠工具本身解决不了但代码里我加了多个查询源对比的逻辑如果公共 DNS 和权威 DNS 返回的 IP 不一致会在结果里打一个高亮标记提醒人工复核。2.3 主机状态检测与批量导入主机状态检测最直接的方法是 ICMP Ping。但 ICMP 在部分云环境会被防火墙拦截或者只允许 ICMP 而禁止 TCP 回包导致误判为宕机。所以我用的是 TCP 端口探测默认探测 80 和 443 端口如果这两个端口至少一个能建立连接就认定主机在线。批量导出方面系统支持三种输入方式手动输入直接在文本框里输入域名每行一个。文件导入上传一个纯文本文件每行一个域名。操作记录直接从查询历史里勾选域名重新查询。这个功能做起来不难但很解决问题。我每次用完都会把结果导出成 CSV归档到本地方便月底统一看所有域名的状态变化。3. 关键环节实现从零搭一个查询服务3.1 环境准备与目录结构项目使用 Python 3.9 Flask数据库选了 SQLite因为本地工具没必要上 MySQL。核心依赖就三个flask、dnspython、python-whois。安装命令很简单pip install flask dnspython python-whois目录结构尽量保持清晰我习惯这样组织ej99domain/ ├── app.py # Flask 入口 ├── whois_check.py # WHOIS 查询与解析 ├── dns_check.py # DNS 解析模块 ├── host_check.py # 主机状态检测模块 ├── templates/ │ └── index.html # 查询页面 └── history.db # SQLite 数据库app.py里只放路由和调度逻辑各个查询模块独立成文件这样后续加接口不影响整体结构。如果你要部署到公网建议用 Gunicorn 托管 Flask因为自带的开发服务器扛不住并发。3.2 查询接口设计与参数约束所有查询最终都收敛到同一个后端接口/api/query。前端提交域名列表后后端做三步处理校验域名格式。这一步很多人容易忽略实际上如果不对域名做正则过滤后续所有查询环节都会浪费时间。我用了一个相对宽松的规则只允许字母数字、连字符和点号且至少包含一个点。import re def validate_domain(domain: str) - bool: if len(domain) 253: return False pattern r^[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?)$ return re.match(pattern, domain) is not None按并发批次执行。全部走串行查询在域名数量多时会非常慢我用了线程池单批次并发 10 个域名既能缩短整体耗时又不会因为并发太高触发 WHOIS 服务器的限流。汇总结果并写入历史记录。每次查询之后把结果以 JSON 形式存到 SQLite同时记录查询时间方便之后做趋势对比。3.3 数据存储与导出SQLite 的用法很简单但有一个点要注意写入频繁的时候要显式控制事务否则在高并发下会报database is locked。我在代码里把查询结果的写入操作集中在一次事务里处理失败时整体回滚。导出功能我用的是内存中生成 CSV 字符串的方式用户点击下载时直接把字符串作为响应返回不需要在服务器上落地临时文件干净利落。import csv import io def generate_csv(rows): output io.StringIO() writer csv.writer(output) writer.writerow([域名, 到期时间, DNS服务器, IP地址, 主机状态]) for row in rows: writer.writerow(row) return output.getvalue()整个过程很直接但确实解决了实际问题我不用再复制粘贴到一个 Excel 里手工整理格式系统直接生成一个带表头的 CSV打开就能用。4. 踩坑记录与问题排查4.1 不同后缀的 WHOIS 响应格式差异这是整个项目里最折磨人的一部分。.com域名的 WHOIS 返回是标准的Domain Name: xxx.com这种键值对但.cn域名返回的是中文标签和属性混排的格式.io、.dev这类新顶级域更乱甚至有些直接不开放 WHOIS 端口只提供 RDAP 接口。我的处理方案是维护一个后缀到解析器的映射表每个后缀指定一套正则规则。解析器先执行自定义规则失败了再走通用规则通用规则还失败就直接返回原始文本。这个方法不算优雅但很实用适用性远大于单一规则。这里补充一句RDAP 也就是 Registration Data Access Protocol是 WHOIS 的现代替代方案走 HTTP JSON格式统一安全性也更好。我在新顶级域查询上会优先尝试 RDAP不行再回退到 WHOIS。这个策略实测下来成功率能到 90% 以上。4.2 限流、超时与重试策略查询过程中最容易碰到的问题就是 WHOIS 服务器限流。有些服务器在短时间内收到大量请求会直接断开连接或者返回错误信息。我的解决方案是对每次查询设置 15 秒超时超时后最多重试 2 次每次重试之间随机等待 1 到 3 秒避免触发更严格的限流策略。更细一点的做法是记录每个后缀服务器的查询次数如果某个服务器连续查询超过 20 次就强制暂停 5 秒再继续。这个限制可能让单次批量查询略微变慢但能避免把服务器“惹毛”整个系统的稳定性会明显上升。如果你也在做类似工具我特别建议在代码里给每个查询步骤都打印时间戳日志。排查问题的时候日志会直接告诉你瓶颈在哪一步是 WHOIS 服务器慢还是 DNS 解析超时还是端口探测被防火墙拦截。4.3 隐私保护与字段缺失很多域名开启了 WHOIS 隐私保护注册人姓名、邮箱、电话都会显示为代理信息。处理这种数据的时候如果系统直接把代理信息拿来用会给后续的数据统计造成很大干扰。所以我在解析结果里增加了“隐私保护开启”这个标记位只要发现注册人信息里出现隐私保护服务商的常见关键词就自动把该条记录的注册人信息置为空并在前端显示灰色的提示。这样做还有一个额外的好处在统计域名资产时会自动绕开因为隐私保护造成的“伪归属地误判”让分析结果更接近真实情况。5. 实际使用心得与后续扩展5.1 使用中发现的几个优化点系统上线之后我日常使用频率最高的其实是批量查询和导出功能。每次拿到一个域名列表最先看的就是到期时间和 NS 记录有没有变动。如果出现同一批域名的 NS 记录指向了同一个新服务器就会重点回访一下确认是不是做了批量迁移。另外一个让我意外好用的功能是“历史对比”。因为每次查询记录都存在 SQLite 里只需要做一次简单的分组查询就能列出哪些域名的解析 IP 变了、哪些的到期时间变了。这比在 Excel 里维护数据靠谱得多因为数据是自动收集的不会忘记更新。5.2 后续可以扩展的方向这个项目目前停留在 v1.0 版本后续我觉得有几个方向值得继续做接入更多 API 数据源比如证书透明日志用来排查域名是否被签发未知证书。增加定时巡检能力配合 cron 或者系统计划任务定时执行查询发现异常自动发邮件告警。把前端界面从简单表单升级成带状态图标的仪表盘一眼看出哪些域名有异常。不过话说回来工具做得再好最终还是回归到需求本身。我这个系统的核心目标从来不是做一个功能花哨的“大平台”而是帮自己在几分钟内搞清楚一批域名的基础状态。如果你也有类似的域名管理痛点按照上面这些思路从头实现一遍现场动手调试的过程比直接拿现成脚本拷贝然后跑通能学到更多。遇到某个模块实现不够顺手的时候也不用急先回到最核心的流程上抓大放小第一版能跑起来就是阶段性的胜利。本文还有配套的精品资源点击获取
返回列表