如何最好地并行化网页解析?

Joa*_*nge 5 .net c# parallel-processing multithreading

我正在使用html敏捷包来解析论坛网站的各个页面.因此,解析方法返回页面链接上的所有主题/线程链接,作为参数传递.我在一个集合中收集所有已解析页面的所有主题链接.

在那之后,我检查它们是否在我Dictionary已经查看的URL上,如果它们不是,那么我将它们添加到新列表中,UI显示此列表,这基本上是自上次创建的新主题/线程.

由于所有这些操作看起来都是独立的,因此最好的并行方法是什么?

我应该使用.NET 4.0 Parallel.For/ForEach吗?

无论哪种方式,我如何在一个集合中收集每个页面的结果?或者这不是必要的吗?

Dictionary每当解析方法完成时,我是否可以从我的集中式读取同时查看它们是否在那里?

如果我运行这个程序4000页,它需要90分钟,如果我可以使用我所有的8个核心在约10分钟内完成相同的任务将是很好的.

Kir*_*ril 1

之后,我检查它们是否在我已查看的 url 字典中,如果不在,则将它们添加到新列表中,并且 UI 显示此列表,这基本上是自上次以来创建的新主题/线程。由于所有这些操作看起来都是独立的,那么并行化的最佳方法是什么?

您当然可以使用 Parallel.For/ForEach 来做到这一点,但您应该稍微考虑一下爬虫的设计。大多数爬虫倾向于专门使用多个线程来爬行,并且每个线程都与负责获取页面的页面获取客户端相关联(在您的情况下,可能使用 / WebRequestWebResponse我建议阅读这些论文:

如果你实现这个Mercator设计,那么你应该能够轻松地每秒下载 50 个页面,因此 80 秒内将下载 4000 个页面。

不管怎样,我怎样才能将每个页面的结果收集到一个集合中?

您可以将结果存储在 a 中ConcurrentDictionary<TKey, TValue>,就像达林提到的那样。您不需要在值中存储任何内容,因为您的密钥将是链接/URL,但是如果您正在执行URL-seen 测试,那么您可以将每个链接/URL 散列为整数,然后将散列存储为键和链接/URL 作为值。

或者说这是没有必要的?

这完全由您决定什么是必要的,但如果您正在执行 URL-seen 测试,那么它是必要的。

每当解析方法完成时,我是否可以从集中式字典中读取它们,以查看它们是否同时存在?

是的,ConcurrentDictionary允许多个线程同时读取,所以应该没问题。如果您只想查看链接是否已被抓取,它会很好地工作。

如果我运行这个程序 4000 个页面,大约需要 90 分钟,如果我可以使用所有 8 个核心在大约 10 分钟内完成相同的任务,那就太好了。

如果你的爬虫设计得足够好,你应该能够在普通台式电脑上在大约 57 秒内下载和解析(提取所有链接)4000 个页面......我在WebRequest4GB 上使用标准 C# 大致得到了这些结果, i5 3.2 GHz PC,具有 10 Mbps 连接。