首页 > 解决方案 > 考虑到以下网络限制,如何非常快速地抓取 XML?

问题描述

我有一个在用户发出请求时正在运行的 .Net 爬虫(因此,它需要快速)。它实时抓取 400 多个链接。(这是业务要求。)

问题:我需要检测链接是 xml(想想 rss 或 atom 提要)还是 html。如果链接是 xml,那么我继续处理,但如果链接是 html,我可以跳过它。通常,我有 2 个 xml(s) 和 398+ 个 html(s)。目前,我有多个线程,但处理速度仍然很慢,通常 75 秒运行 10 个线程,400 多个链接,或 280 秒运行 1 个线程。(我想添加更多线程,但见下文..)

我面临的挑战是我阅读流如下:

var request = WebRequest.Create(requestUriString: uri.AbsoluteUri);
// ....
var response = await request.GetResponseAsync();
//....
using (var reader = new StreamReader(stream: response.GetResponseStream(), encoding: encoding)) {
                        char[] buffer = new char[1024];
                        await reader.ReadAsync(buffer: buffer, index: 0, count: 1024);
                        responseText = new string(value: buffer);
}
// parse first byts of reasponseText to check if xml 

问题是我只获得 1024 的优化是非常无用的,因为 GetResponseAsync 无论如何都在下载整个流,正如我所看到的。(我拥有的另一个选项是查找标头 ContentType,但这与 AFAIK 非常相似,因为无论如何我都会获得内容 - 以防您不建议使用迄今为止我没有使用的 OPTIONS - 此外xml 可能被错误地标记为内容类型(?),我会错过一些内容。)

如果我缺少任何优化,请提供帮助,因为我已经没有想法了。

(我确实考虑通过将负载分散到多台服务器上来优化这个设计,这样我就可以通过并行性来平衡网络,但这与当前架构相比有点变化,我目前无法承受。)

标签: c#asp.net-coreweb-crawler

解决方案


如果您可以依赖 Content-Type,则使用 HEAD 请求可以显着加快请求速度。

例如

HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(new HttpRequestMessage() { Method = HttpMethod.Head});

只显示基本用法。显然,您需要添加 uri 和请求所需的任何其他内容。

还要注意的是,即使有 10 个线程,400 个请求也可能总是需要很长时间。400/10 表示顺序有 40 个请求。除非请求是到关闭的服务器,否则 200 毫秒将是一个很好的响应时间,这意味着至少 8 秒。除非您增加线程数量以并行处理更多请求,否则可能很慢的 Ovsersea 服务很容易将其推迟到 30-40 秒的不可避免的延迟。

数据流(任务并行库)对于编写具有方便的 MaxDegreeOfParallelism 属性的并行管道非常有帮助,以便轻松调整可以运行的并行实例的数量。


推荐阅读