我正在使用html敏捷包来解析论坛网站的各个页面。因此,解析方法返回页面链接上的所有主题/线程链接,作为参数传递。我在一个集合中收集所有已解析页面的所有主题链接。
之后,我检查它们是否在Dictionary
已查看的网址上,如果不是,则将其添加到新列表中,UI显示此列表,这基本上是新主题/自上次创建以来的线程。
由于所有这些操作看起来都是独立的,因此最好的并行方法是什么?
我应该使用.NET 4.0的Parallel.For/ForEach
吗?
无论哪种方式,我如何在单个集合中收集每个页面的结果?或者这不是必要的吗?
每当解析方法完成并同时查看它们是否存在时,我是否可以从集中式Dictionary
读取?
如果我运行这个程序4000页,需要90分钟,如果我可以使用我所有的8个内核在~10分钟内完成相同的任务,那就太棒了。
答案 0 :(得分:4)
Parallel.For/ForEach
与ConcurrentDictionary<TKey, TValue>
相结合以在不同线程之间共享状态似乎是实现此目的的好方法。并发字典确保从多个线程安全读/写。
答案 1 :(得分:1)
之后,我检查它们是否在我已经查看过的URL字典中,如果不是,那么我将它们添加到新列表中,UI显示此列表,这基本上是新创建的主题/线程上次。 由于所有这些操作看起来都是独立的,因此最好的并行方法是什么?
你当然可以使用Parallel.For / ForEach来做到这一点,但你应该考虑一下爬虫的设计。大多数抓取工具倾向于将多个线程专用于爬网,并且每个线程都与一个页面获取客户端相关联,该客户端负责获取页面(在您的情况下,可能使用WebRequest
/ WebResponse
)我建议阅读这些文件:
如果您实施Mercator
设计,那么您应该可以轻松地每秒下载50页,因此您将在80秒内下载4000页。
无论哪种方式,我如何在单个集合中收集每个页面的结果?
您可以将结果存储在ConcurrentDictionary<TKey, TValue>
中,就像Darin提到的那样。您不需要在值中存储任何内容,因为您的密钥将是链接/ URL,但是如果您执行URL-seen Test,则可以将每个链接/ URL散列为整数,然后存储散列作为键,链接/ URL作为值。
或者这不是必要的吗?
完全取决于你决定什么是必要的,但是如果你正在执行一个URL看到的测试,那么这是必要的。
每当解析方法完成时,我是否可以从我的集中式字典中读取它们是否同时存在?
是的,ConcurrentDictionary
允许多个线程同时读取,所以应该没问题。如果您只想查看链接是否已被抓取,它将正常工作。
如果我运行这个程序4000页,需要90分钟,如果我可以使用我所有的8个内核在~10分钟内完成相同的任务,那就太棒了。
如果你设计的爬虫足够好,你应该能够在普通台式PC上大约57秒内下载并解析(提取所有链接)4000页......我大致得到了标准C#的结果{ {1}}在4GB,i5 3.2 GHz PC上,连接速度为10 Mbps。