首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP Whois 域名查詢函式:支援多頂級域名與自動伺服器選擇

     編輯:PHP 相關知識

Whois 協定可查詢域名註冊資訊。不同頂級域名 (TLD) 由不同註冊局管理,查詢伺服器各異。本文提供一個完整的 whoisQuery() 函式,內建常見 TLD 伺服器對照表、自動解析域名後綴、支援快取與錯誤處理,並說明現代 RDAP 替代方案。

一、核心函式實作

<?php
/**
 * Whois 域名查詢
 *
 * @param string $domain 完整域名 (含或不含 www./https://)
 * @param int    $timeout 連線逾時秒數
 * @return array ['raw' => 原始回應, 'available' => 是否可註冊, 'parsed' => 解析後關鍵欄位]
 * @throws Exception 查詢失敗
 */
function whoisQuery(string $domain, int $timeout = 10): array {
    // 1. 正規化域名
    $domain = strtolower(trim($domain));
    $domain = preg_replace('~^https?://~i', '', $domain);
    $domain = preg_replace('~^www\.~i', '', $domain);
    $domain = explode('/', $domain)[0]; // 取第一段
    $domain = trim($domain);

    if (!preg_match('~^[a-z0-9.-]+\.[a-z]{2,}$~i', $domain)) {
        throw new Exception("無效域名格式: $domain");
    }

    // 2. 取得 TLD (頂級域名)
    $parts = explode('.', $domain);
    $tld = end($parts); // 簡易取最後一段,實務建議用 Public Suffix List

    // 3. TLD -> Whois 伺服器對照表 (部分常見)
    $servers = [
        // 通用頂級域
        'com'   => 'whois.verisign-grs.com',
        'net'   => 'whois.verisign-grs.com',
        'org'   => 'whois.pir.org',
        'info'  => 'whois.afilias.net',
        'biz'   => 'whois.biz',
        'name'  => 'whois.nic.name',
        'pro'   => 'whois.registrypro.pro',
        'xyz'   => 'whois.nic.xyz',
        'top'   => 'whois.nic.top',
        'club'  => 'whois.nic.club',
        'online'=> 'whois.nic.online',
        'site'  => 'whois.nic.site',
        // 國家代碼頂級域
        'cn'    => 'whois.cnnic.cn',
        'tw'    => 'whois.twnic.net.tw',
        'hk'    => 'whois.hkirc.hk',
        'jp'    => 'whois.jprs.jp',
        'kr'    => 'whois.kisa.or.kr',
        'sg'    => 'whois.sgnic.sg',
        'my'    => 'whois.mynic.my',
        'th'    => 'whois.thnic.co.th',
        'vn'    => 'whois.vnnic.vn',
        'id'    => 'whois.pandi.or.id',
        'ph'    => 'whois.nic.ph',
        'au'    => 'whois.auda.org.au',
        'nz'    => 'whois.srs.net.nz',
        'uk'    => 'whois.nic.uk',
        'de'    => 'whois.denic.de',
        'fr'    => 'whois.nic.fr',
        'ru'    => 'whois.tcinet.ru',
        'br'    => 'whois.registro.br',
        'ca'    => 'whois.cira.ca',
        'us'    => 'whois.nic.us',
        'eu'    => 'whois.eu',
        'io'    => 'whois.nic.io',
        'ai'    => 'whois.nic.ai',
        'co'    => 'whois.nic.co',
        'me'    => 'whois.nic.me',
        'tv'    => 'whois.nic.tv',
        'cc'    => 'whois.nic.cc',
        'ws'    => 'whois.worldsite.ws',
        // 特殊
        'edu'   => 'whois.educause.edu',
        'gov'   => 'whois.nic.gov',
        'mil'   => 'whois.nic.mil',
        'int'   => 'whois.iana.org',
        'arpa'  => 'whois.iana.org',
    ];

    if (!isset($servers[$tld])) {
        // 嘗試 IANA 根伺服器查詢授權伺服器
        $servers[$tld] = 'whois.iana.org';
    }

    $server = $servers[$tld];

    // 4. 建立 TCP 連線查詢 (Whois 使用 Port 43)
    $fp = @fsockopen($server, 43, $errno, $errstr, $timeout);
    if (!$fp) {
        throw new Exception("無法連線至 Whois 伺服器 $server: $errstr ($errno)");
    }

    stream_set_timeout($fp, $timeout);
    fwrite($fp, $domain . "\r\n");

    $response = '';
    while (!feof($fp)) {
        $response .= fread($fp, 8192);
    }
    fclose($fp);

    // 5. 簡易判斷是否可註冊 (不同註冊局關鍵字不同)
    $availableKeywords = [
        'no match',
        'not found',
        'available',
        'free',
        'no entries',
        'domain not found',
        'status: available',
    ];
    $available = false;
    $lowerResp = strtolower($response);
    foreach ($availableKeywords as $kw) {
        if (strpos($lowerResp, $kw) !== false) {
            $available = true;
            break;
        }
    }

    // 6. 簡易解析關鍵欄位 (各註冊局格式差異大,僅示範常見)
    $parsed = [];
    $patterns = [
        'registrar'      => '/Registrar:\s*(.+)/i',
        'creation_date'  => '/(?:Creation Date|Created On):\s*(.+)/i',
        'expiry_date'    => '/(?:Expir|Registry Expiry Date):\s*(.+)/i',
        'name_servers'   => '/Name Server:\s*(.+)/i',
        'status'         => '/Status:\s*(.+)/i',
    ];
    foreach ($patterns as $key => $pattern) {
        if (preg_match_all($pattern, $response, $matches)) {
            $parsed[$key] = array_map('trim', $matches[1]);
        }
    }

    return [
        'domain'    => $domain,
        'server'    => $server,
        'raw'       => $response,
        'available' => $available,
        'parsed'    => $parsed,
    ];
}

二、使用範例

<?php
try {
    $result = whoisQuery('google.com');
    echo "域名: {$result['domain']}\n";
    echo "伺服器: {$result['server']}\n";
    echo "可註冊: " . ($result['available'] ? '是' : '否') . "\n";
    echo "註冊商: " . ($result['parsed']['registrar'][0] ?? 'N/A') . "\n";
    echo "建立日期: " . ($result['parsed']['creation_date'][0] ?? 'N/A') . "\n";
    echo "到期日期: " . ($result['parsed']['expiry_date'][0] ?? 'N/A') . "\n";
} catch (Exception $e) {
    echo "查詢失敗: " . $e->getMessage();
}

三、效能優化:快取機制

Whois 查詢較慢 (通常 0.5~3 秒),且註冊局有頻率限制。**必須加入快取**:

<?php
function whoisQueryCached(string $domain, int $ttl = 86400): array {
    $cacheKey = 'whois:' . md5(strtolower($domain));
    // 假設使用 Redis
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);

    $cached = $redis->get($cacheKey);
    if ($cached !== false) {
        return json_decode($cached, true);
    }

    $result = whoisQuery($domain);
    $redis->setex($cacheKey, $ttl, json_encode($result));
    return $result;
}

四、現代替代方案:RDAP (Registration Data Access Protocol)

  • HTTP/JSON 介面,取代純文字 Whois
  • 標準化回應格式,易於解析
  • 支援國際化、權限控制、重導向
  • 查詢端點:https://rdap.verisign.com/com/v1/domain/example.com
function rdapQuery(string $domain): array {
    $url = "https://rdap.org/domain/$domain"; // 自動導向至正確註冊局
    $json = @file_get_contents($url);
    return $json ? json_decode($json, true) : [];
}

五、注意事項與法律提醒

  • 頻率限制:多數註冊局限制每 IP 每秒/分鐘查詢次數,違規會被封禁 IP。
  • 資料準確性:Whois 資料可能過時、隱私保護 (GDPR 後大多數個人資訊隱藏)。
  • 法律合規:批次查詢、自動化搶註可能違反《反網路濫用條例》、ICANN 政策、註冊局條款。
  • Public Suffix List:正確解析 TLD 應使用 Public Suffix List,而非簡單取最後一段 (如 co.uk, com.tw 為雙段 TLD)。

六、總結

whoisQuery() 提供完整的域名查詢功能,內建伺服器對照、可用性判斷、關鍵欄位解析。生產環境**必須**搭配快取、頻率控制、錯誤重試,並關注 RDAP 遷移趨勢。嚴格遵守查詢頻率限制與法律法規,避免 IP 被封禁或法律風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved