c# - 考虑到以下网络限制,如何非常快速地抓取 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 可能被错误地标记为内容类型(?),我会错过一些内容。)
如果我缺少任何优化,请提供帮助,因为我已经没有想法了。
(我确实考虑通过将负载分散到多台服务器上来优化这个设计,这样我就可以通过并行性来平衡网络,但这与当前架构相比有点变化,我目前无法承受。)
解决方案
如果您可以依赖 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 属性的并行管道非常有帮助,以便轻松调整可以运行的并行实例的数量。
推荐阅读
- regex - 上下文无关语法的正则表达式
- java - 最后如何修复 toArray 方法?
- animation - setState 不更新wiget UI
- angular - ngModel errors.pattern 属性在 Angular 模板中始终为 true
- python - 如何使用正则表达式(Python)匹配必须是字母、数字和斜线的单词?
- php - Laravel 私人频道未授权:错误 404
- nginx - 使用代理通行证时如何保留请求的端口?
- html - 提交表单后更改按钮的颜色,特别是 html 表的 tr
- r - 如何使用 quanteda::tokens_select() 删除单字符和双字符标记
- shell - 将文本粘贴为击键