如何快速抓取XML - 考虑到以下网络限制?

use*_*247 6 c# web-crawler asp.net-core

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

问题:我需要检测链接是否是xml(想想rss或atom feed)或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 
Run Code Online (Sandbox Code Playgroud)

问题是我的优化只获得1024是没用的,因为GetResponseAsync正在下载整个流,无论如何,正如我所看到的.(我的另一个选择是查找标题ContentType,但这是非常相似的AFAIK,因为我还是得到了内容 - 如果你不建议使用OPTIONS,我到目前为止没用 - 另外xml可能是内容类型错误标记(?),我将错过一些内容.)

如果有任何我失踪的优化请帮助,因为我的想法已经用完了.

(我的确考虑通过在多个服务器上分散负载来优化这种设计,这样我就可以平衡网络与并行性,但这与目前的体系结构有一些变化,我现在无法负担这一点.)

Tim*_*ews 1

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

例如

HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(new HttpRequestMessage() { Method = HttpMethod.Head});
Run Code Online (Sandbox Code Playgroud)

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

另请注意,即使有 10 个线程,400 个请求也可能总是需要相当长的时间。400/10 表示连续 40 个请求。除非请求是发送到附近的服务器,否则 200 毫秒将是一个很好的响应时间,意味着至少 8 秒。海外服务可能很慢,很容易就会导致 30-40 秒的不可避免的延迟,除非您增加线程数量来并行更多的请求。

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