Python根据域名批量查询服务器所在地的方法

RT,手里有些域名,想按服务器所在地进行分类,请问有干过类似活儿的兄 dei 能否指点一下思路,目前想到的就是研究一下纯真 IP 库


Python根据域名批量查询服务器所在地的方法
5 回复

用了 cdn 的网站你怎么排除?


import socket
import requests
import json
from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def get_ip_from_domain(domain):
    """解析域名获取IP地址"""
    try:
        # 使用socket获取IP,可考虑添加超时设置
        ip = socket.gethostbyname(domain)
        return ip
    except socket.gaierror:
        return None
    except Exception as e:
        print(f"解析 {domain} 时出错: {e}")
        return None

def get_location_from_ip(ip):
    """通过IP查询地理位置(使用ip-api.com免费服务)"""
    if not ip:
        return None
    
    try:
        url = f"http://ip-api.com/json/{ip}"
        response = requests.get(url, timeout=5)
        data = response.json()
        
        if data['status'] == 'success':
            return {
                'ip': ip,
                'country': data.get('country', ''),
                'region': data.get('regionName', ''),
                'city': data.get('city', ''),
                'isp': data.get('isp', ''),
                'org': data.get('org', '')
            }
        return None
    except requests.exceptions.RequestException as e:
        print(f"查询IP {ip} 位置时出错: {e}")
        return None
    except json.JSONDecodeError:
        print(f"解析IP {ip} 响应时出错")
        return None

def batch_query_domains(domains, max_workers=10):
    """批量查询域名服务器所在地"""
    results = []
    
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交所有域名解析任务
        future_to_domain = {
            executor.submit(get_ip_from_domain, domain): domain 
            for domain in domains
        }
        
        # 处理解析结果并提交位置查询
        location_futures = []
        for future in as_completed(future_to_domain):
            domain = future_to_domain[future]
            try:
                ip = future.result()
                if ip:
                    # 提交位置查询任务
                    location_future = executor.submit(get_location_from_ip, ip)
                    location_futures.append((domain, ip, location_future))
                else:
                    results.append({'domain': domain, 'error': '无法解析IP'})
            except Exception as e:
                results.append({'domain': domain, 'error': str(e)})
        
        # 收集位置查询结果
        for domain, ip, location_future in location_futures:
            try:
                location = location_future.result()
                if location:
                    results.append({
                        'domain': domain,
                        'ip': ip,
                        'country': location['country'],
                        'region': location['region'],
                        'city': location['city'],
                        'isp': location['isp'],
                        'org': location['org']
                    })
                else:
                    results.append({'domain': domain, 'ip': ip, 'error': '无法获取位置信息'})
            except Exception as e:
                results.append({'domain': domain, 'ip': ip, 'error': str(e)})
    
    return results

def main():
    # 示例域名列表
    domains = [
        'google.com',
        'github.com',
        'baidu.com',
        'example.com',
        'invalid-domain-test-123.com'  # 无效域名测试
    ]
    
    print("开始批量查询域名服务器所在地...")
    start_time = time.time()
    
    results = batch_query_domains(domains)
    
    # 输出结果
    print(f"\n查询完成,耗时: {time.time() - start_time:.2f}秒")
    print("=" * 80)
    
    for result in results:
        print(f"\n域名: {result['domain']}")
        if 'error' in result:
            print(f"  错误: {result['error']}")
        else:
            print(f"  IP地址: {result['ip']}")
            print(f"  国家: {result['country']}")
            print(f"  地区: {result['region']}")
            print(f"  城市: {result['city']}")
            print(f"  ISP: {result['isp']}")
            print(f"  组织: {result['org']}")

if __name__ == "__main__":
    main()

这个方案分三步走:先用socket解析域名拿IP,再通过ip-api.com的免费API查地理位置,最后用线程池批量处理。注意ip-api.com有频率限制(每分钟45次),生产环境建议用付费API或自建IP库。

现在连静态网站都有 cdn 了

CDN 的直接 pass

没有方法精确地知道一个服务器的地理位置。能想到的办法也只有查 GeoIP 数据库了

回到顶部