如何用C#从指定URL子目录提取.log和.txt格式文件URL
远程URL目录下提取指定后缀文件的实现方法
你原来用的Directory.GetFiles是专门操作本地文件系统的API,完全没法处理HTTP/HTTPS远程URL,所以肯定用不了。要实现远程URL下的文件遍历提取,得根据目标服务器的情况来选方案:
方案一:服务器开启目录列表功能(可直接浏览文件列表)
如果目标服务器允许目录索引(比如Apache、Nginx开启了目录浏览,访问URL会显示文件和子目录的列表页面),可以通过爬取页面+解析HTML的方式实现:
实现步骤
- 用
HttpClient请求目标URL的页面内容 - 解析HTML提取所有
<a>标签的链接 - 过滤出后缀为
.log或.txt的文件链接,将相对路径转为绝对URL - 递归处理子目录的链接,重复上述步骤
C#示例代码
需要先安装HtmlAgilityPack NuGet包来解析HTML:
using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using HtmlAgilityPack; public class RemoteFileScraper { private static readonly HttpClient _httpClient = new HttpClient(); private static readonly HashSet<string> _targetExtensions = new HashSet<string> { ".log", ".txt" }; private static readonly HashSet<string> _visitedUrls = new HashSet<string>(); // 避免重复访问 public static async Task<List<string>> GetTargetFilesAsync(string baseUrl) { var result = new List<string>(); if (!_visitedUrls.Add(baseUrl)) return result; try { var response = await _httpClient.GetAsync(baseUrl); response.EnsureSuccessStatusCode(); var htmlContent = await response.Content.ReadAsStringAsync(); var doc = new HtmlDocument(); doc.LoadHtml(htmlContent); foreach (var aNode in doc.DocumentNode.SelectNodes("//a[@href]")) { var href = aNode.GetAttributeValue("href", string.Empty); if (string.IsNullOrEmpty(href) || href.StartsWith("#") || href.StartsWith("?")) continue; // 拼接绝对URL var absoluteUrl = new Uri(new Uri(baseUrl), href).ToString(); // 判断是文件还是子目录 if (absoluteUrl.EndsWith("/")) { // 递归处理子目录 var subDirFiles = await GetTargetFilesAsync(absoluteUrl); result.AddRange(subDirFiles); } else { // 过滤目标后缀的文件 var extension = System.IO.Path.GetExtension(absoluteUrl).ToLower(); if (_targetExtensions.Contains(extension)) { result.Add(absoluteUrl); } } } } catch (Exception ex) { Console.WriteLine($"访问 {baseUrl} 出错: {ex.Message}"); } return result; } } // 使用示例 // var files = await RemoteFileScraper.GetTargetFilesAsync("https://example.com/folder1");
方案二:调用服务器提供的文件列表API
如果目标服务器有专门的接口(比如REST API)返回文件结构数据(JSON/XML格式),直接调用API解析是更可靠的方式,不用依赖页面结构的变化:
C#示例代码(假设API返回JSON数组)
using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using System.Text.Json; public class FileApiClient { private static readonly HttpClient _httpClient = new HttpClient(); private static readonly HashSet<string> _targetExtensions = new HashSet<string> { ".log", ".txt" }; public static async Task<List<string>> GetTargetFilesAsync(string apiUrl) { var result = new List<string>(); try { var response = await _httpClient.GetAsync(apiUrl); response.EnsureSuccessStatusCode(); var jsonContent = await response.Content.ReadAsStringAsync(); // 假设API返回的是包含文件信息的数组,每个元素有"url"字段 var files = JsonSerializer.Deserialize<List<FileInfo>>(jsonContent); if (files != null) { foreach (var file in files) { var extension = System.IO.Path.GetExtension(file.Url).ToLower(); if (_targetExtensions.Contains(extension)) { result.Add(file.Url); } // 如果有子目录API,递归调用 if (!string.IsNullOrEmpty(file.SubDirectoryApiUrl)) { var subDirFiles = await GetTargetFilesAsync(file.SubDirectoryApiUrl); result.AddRange(subDirFiles); } } } } catch (Exception ex) { Console.WriteLine($"调用API出错: {ex.Message}"); } return result; } // 对应API返回的文件信息结构 private class FileInfo { public string Url { get; set; } public string SubDirectoryApiUrl { get; set; } } } // 使用示例 // var files = await FileApiClient.GetTargetFilesAsync("https://example.com/api/files?path=/folder1");
注意事项
- 方案一依赖服务器的目录列表页面结构,如果页面样式或链接规则变化,代码可能失效
- 两种方案都需要处理HTTP请求的异常(比如403禁止访问、网络错误等)
- 不要频繁请求服务器,避免触发反爬机制
内容的提问来源于stack exchange,提问作者Karmesh Duggar
相关产品推荐
相关产品推荐

