File size: 4,240 Bytes
5044684
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import gradio as gr
import socket
import time

def check_dns_resolution(domain):
    """
    尝试将域名解析为IP地址。
    这是测试DNS问题的最直接方法。
    返回一个包含结果的元组 (domain, status, detail)。
    """
    try:
        # socket.gethostbyname 是对系统DNS解析器的直接调用。
        # 如果此调用失败,则说明从Space内部无法解析该域名。
        ip_address = socket.gethostbyname(domain)
        return (domain, "✅ 可访问", f"成功解析到IP: {ip_address}")
    except socket.gaierror as e:
        # socket.gaierror 是专门处理地址相关错误的异常(例如,主机名未知)。
        return (domain, "❌ 无法访问", f"DNS解析失败: {e}")
    except Exception as e:
        return (domain, "❌ 出错", f"发生未知错误: {e}")

def batch_test_domains(domain_list_str, progress=gr.Progress(track_tqdm=True)):
    """
    对给定的域名列表进行批量测试,并生成Markdown格式的报告。
    """
    if not domain_list_str or not domain_list_str.strip():
        return "⚠️ 请在文本框中输入至少一个域名。"

    # 将输入字符串分割成域名列表,并清除空白行和多余的空格
    domains_to_test = [d.strip() for d in domain_list_str.split('\n') if d.strip()]
    if not domains_to_test:
        return "⚠️ 输入无效,请输入有效域名。"

    total_domains = len(domains_to_test)
    results = []

    # 使用串行循环代替并发,并加入延迟,以避免触发速率限制
    for i, domain in enumerate(domains_to_test):
        # 更新进度条,这能保持与前端的连接,防止超时
        progress(i / total_domains, desc=f"正在测试 ({i+1}/{total_domains}): {domain}")
        
        # 执行DNS解析
        result = check_dns_resolution(domain)
        results.append(result)
        
        # !!! 重要: 加入短暂延迟,防止请求过于密集而被服务器限制 !!!
        time.sleep(0.25)

    # --- 开始生成报告 ---
    accessible_domains = []
    inaccessible_domains = []

    for domain, status, detail in results:
        # 使用 Markdown 的代码格式 `domain` 来突出显示域名
        formatted_line = f"`{domain}` - {detail}"
        if "可访问" in status:
            accessible_domains.append(formatted_line)
        else:
            inaccessible_domains.append(formatted_line)
    
    report = f"## 批量测试报告 (共测试 {total_domains} 个域名)\n\n"
    
    report += f"### ✅ 可访问的域名 ({len(accessible_domains)} 个)\n"
    if accessible_domains:
        report += "\n".join([f"- {d}" for d in accessible_domains])
    else:
        report += "无"
        
    report += f"\n\n### ❌ 无法访问或出错的域名 ({len(inaccessible_domains)} 个)\n"
    if inaccessible_domains:
        report += "\n".join([f"- {d}" for d in inaccessible_domains])
    else:
        report += "无"
        
    return report

# --- Gradio 应用界面 ---
with gr.Blocks(theme=gr.themes.Default(primary_hue="blue", secondary_hue="blue")) as demo:
    gr.Markdown(
        """
        # Hugging Face Space 出站网络可访问性测试 (优化版)
        在下面的文本框中输入或粘贴您需要测试的域名列表(每行一个)。
        工具将以安全、稳定的方式逐个测试,并生成清晰的报告,以避免IP被临时限制。
        """
    )

    with gr.Row():
        domain_input = gr.Textbox(
            lines=15, 
            label="域名列表 (每行一个)", 
            placeholder="www.google.com\nwww.facebook.com\nhuggingface.co\napi.openai.com\n..."
        )
    
    submit_btn = gr.Button("🚀 开始批量测试", variant="primary")
    
    output_report = gr.Markdown(label="测试报告")
    
    # 将按钮点击事件连接到主函数
    submit_btn.click(
        fn=batch_test_domains,
        inputs=domain_input,
        outputs=output_report
    )
    
    gr.Examples(
        [
            "www.google.com\ngithub.com\nhuggingface.co\nwww.wikipedia.org",
            "www.facebook.com\nwww.instagram.com\nwww.youtube.com\nweb.whatsapp.com"
        ],
        inputs=domain_input
    )

demo.launch()