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(); /// /// 初始化代理池并验证可用性 /// /// CSV 文件路径,每行格式:ip,port /// 可用性验证的测试地址,建议用目标网站或者 https://httpbin.org/ip 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,请检查代理池是否失效"); } /// /// 验证代理是否可用 /// private static async Task 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; } } /// /// 使用随机代理发起 GET 请求,并支持重试 /// public static async Task 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("多次尝试使用代理请求失败"); } }