C#.NET控制台下载维基百科图片报403 User-Agent错误求解决方案
解决建议
- 优化User-Agent格式:当前的UA结构不符合标准要求,建议调整为
[程序名]/[版本号] ([联系方式]; [用途说明])的结构化格式,可替换为CarnivoraImageBot/1.0 (your-email@example.com; 教育用途,单次下载小于300张食肉目动物图片),避免使用零散的自然语言描述结构。 - 替换过时的WebClient类:WebClient是.NET Framework时代的遗留API,请求头处理逻辑存在限制,建议改用官方推荐的HttpClient实现请求,同时将HttpClient声明为静态全局变量,避免重复实例化导致的套接字资源浪费。
- 补充必要的通用请求头:额外添加Accept等常规请求头,降低被反爬策略拦截的概率,例如添加
Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8。 - 增加异常捕获与重试逻辑:单次请求失败后不要直接终止程序,捕获请求异常后等待一段时间再重试2-3次,避免偶发的服务器拦截导致程序中断。
- 检查路径合法性:替换文件名中的非法字符,避免动物名称中的特殊符号导致本地保存路径错误。
- 若调整后仍触发403,可将单次下载后的等待间隔延长到10秒,进一步降低请求频率。
修改后的参考代码:
// 建议将HttpClient声明为静态全局变量,避免重复实例化导致的套接字资源浪费 private static readonly HttpClient _httpClient = new HttpClient(); static async Task DownloadImagesAsync() { // 配置统一的请求头,仅需设置一次 _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("CarnivoraImageBot/1.0 (your-email@example.com; 教育用途,单次下载小于300张食肉目动物图片)"); _httpClient.DefaultRequestHeaders.Accept.ParseAdd("image/avif,image/webp,image/apng,image/*,*/*;q=0.8"); var files = Directory.GetFiles(@"C:\projects\CarnivoraData", "*", SearchOption.AllDirectories); var saveDir = @"C:\projects\CarnivoraImages\"; // 确保保存目录存在 if (!Directory.Exists(saveDir)) { Directory.CreateDirectory(saveDir); } foreach (var path in files) { AnimalData data = JsonSerializer.Deserialize<AnimalData>(await File.ReadAllTextAsync(path)); var imageUrl = "https:" + data.Imageurl; var savePath = Path.Combine(saveDir, $"{data.Name}{Path.GetExtension(data.Imageurl)}"); // 替换文件名中的非法字符,避免路径错误 savePath = string.Join("_", savePath.Split(Path.GetInvalidFileNameChars())); // 增加重试逻辑 int retryCount = 0; bool downloadSuccess = false; while (retryCount < 3 && !downloadSuccess) { try { var imageBytes = await _httpClient.GetByteArrayAsync(imageUrl); await File.WriteAllBytesAsync(savePath, imageBytes); downloadSuccess = true; Console.WriteLine($"已下载:{data.Name}"); } catch (HttpRequestException ex) { retryCount++; Console.WriteLine($"下载{data.Name}失败,第{retryCount}次重试,错误信息:{ex.Message}"); // 重试等待时间逐次增加 await Task.Delay(10000 * retryCount); } } // 每次下载完成等待5秒 await Task.Delay(5000); } }
内容的提问来源于stack exchange,提问作者Guye Incognito
相关产品推荐
相关产品推荐

