tuiwucarrer/Admin.NET/Admin.NET.Core/Service/ZYFusion/ProxyHelper.cs

110 lines
3.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Admin.NET.Core.Service;
public static class ProxyHelper
{
private static List<(string ip, int port)> _proxyList = new();
private static readonly Random _random = new();
/// <summary>
/// 初始化代理池并验证可用性
/// </summary>
/// <param name="filePath">CSV 文件路径每行格式ip,port</param>
/// <param name="testUrl">可用性验证的测试地址,建议用目标网站或者 https://httpbin.org/ip</param>
public static async Task LoadAndValidateProxiesAsync(string filePath, string testUrl = "https://httpbin.org/ip")
{
if (!File.Exists(filePath)) throw new FileNotFoundException("代理IP文件不存在", filePath);
var lines = File.ReadAllLines(filePath);
var tempList = new List<(string ip, int port)>();
foreach (var line in lines.Skip(1)) // 跳过表头
{
var parts = line.Split(',');
if (parts.Length >= 2 && int.TryParse(parts[1], out var port))
{
tempList.Add((parts[0], port));
}
}
// 异步验证代理是否可用
var tasks = tempList.Select(proxy => IsProxyAvailableAsync(proxy.ip, proxy.port, testUrl));
var results = await Task.WhenAll(tasks);
_proxyList = tempList.Where((proxy, index) => results[index]).ToList();
Console.WriteLine($"✅ 验证通过的代理数量:{_proxyList.Count}");
if (!_proxyList.Any())
throw new Exception("没有可用的代理IP请检查代理池是否失效");
}
/// <summary>
/// 验证代理是否可用
/// </summary>
private static async Task<bool> IsProxyAvailableAsync(string ip, int port, string testUrl)
{
try
{
var handler = new HttpClientHandler
{
Proxy = new WebProxy(ip, port),
UseProxy = true,
};
using var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromSeconds(5);
var response = await client.GetAsync(testUrl);
return response.IsSuccessStatusCode;
}
catch
{
return false;
}
}
/// <summary>
/// 使用随机代理发起 GET 请求,并支持重试
/// </summary>
public static async Task<string> GetWithRandomProxyAsync(string url, int maxRetry = 5, int delayBetweenRetry = 1000)
{
if (!_proxyList.Any()) throw new Exception("代理列表为空,请先调用 LoadAndValidateProxiesAsync()");
for (int attempt = 0; attempt < maxRetry; attempt++)
{
var (ip, port) = _proxyList[_random.Next(_proxyList.Count)];
try
{
var handler = new HttpClientHandler
{
Proxy = new WebProxy(ip, port),
UseProxy = true,
};
using var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromSeconds(10);
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
Console.WriteLine($"❌ 代理 {ip}:{port} 请求失败(第 {attempt + 1} 次): {ex.Message}");
await Task.Delay(delayBetweenRetry);
}
}
throw new Exception("多次尝试使用代理请求失败");
}
}