1

我正在用 C# 编写一个网络爬虫供我个人使用。它的主要目的是从它爬取的网页下载图像。除了下载的图像,它不会保存网页中的任何数据。

我有一些逻辑将爬虫访问的所有 URL 的文字字符串存储在列表中。这对于短时间的抓取会话来说已经足够了,但我想当抓取工具在一个包含数万个 URL 的列表中进行查找时,这将开始成为较长会话的瓶颈。我还在我的 URL 队列中进行查找,以便在等待抓取的 URL 队列中没有重复的 URL。

我的问题分为两部分:

1)目前我没有在爬行会话之间存储任何数据,这现在很好。当爬虫运行时,有没有比简单的字符串列表更好的方法来存储已经访问过的 URL?

2) 如果我要开始在磁盘上永久存储数据以供多个会话使用,在这种情况下,您建议如何存储访问过的 URL?

4

1 回答 1

3

这在很大程度上取决于您的爬虫爬行的速度。如果您有一个单线程爬虫,那么平均而言,您不会比每秒一页做得更好。因此,您可以使用HashSet来存储您访问过的 URL。或者,如果您想保存有关您访问过的 URL 的信息,您可以使用Dictionary<string, UrlInfo>UrlInfo您定义的类包含您要保留的有关每个访问过的 URL 的信息。

每天 86,400 秒,HashSetDictionary将存储相当多天的数据。

但您可能不想多次下载同一张图片。因此,使用我所说的“离线”或“爬行-过程-爬行”模型可能会更好。这是它的工作原理。

当您开始爬网时,您会访问(例如)您已识别的几千个页面。您下载页面,提取链接,然后将这些链接写入日志文件。如果您找到图像,则下载并保存这些图像。您访问的每个页面也会被写入文件。

访问完这些页面后,您将停止爬虫。您现在有两个保存在文件中的列表:您访问过的页面和您找到的链接。

对访问过的链接进行排序,并将它们与您之前访问过的页面列表合并。随着时间的推移,该文件可能会变得相当大。

对您提取的链接列表进行排序,并删除重复项。然后根据您已经访问过的页面列表检查这些链接。这是最简单的合并。如果该链接已被访问过,则丢弃它。否则,将其写入将在下一次抓取会话中使用的文件。

使用简单的数据库会更容易,但请注意数据库会变得非常大。使用数据库,您不必爬行过程爬行。相反,您可以根据数据库检查提取的每个链接,然后立即保存或丢弃它。

但是,请理解,您将很难访问数据库。我的爬虫经验是,平均而言,一个网页包含超过 100 个链接(即<a href="...">.这不包括图像。你将使用单线程爬虫每秒至少 100 次访问该数据库。

您会遇到的另一个问题是您无法访问找到的每个 URL。随着时间的推移,我发现在我从普通网页中提取的 100 个链接中,有 10 个是我以前从未见过的新链接。因此,对于我阅读的每一页,我都会发现还有 10 页我没有读过。最终,您将需要一些方法来过滤掉不太可能将您引导至图像的 URL。

跟踪您访问过的 URL 的另一种方法是使用Bloom Filter。我在我的网络爬虫中使用了这些效果。

于 2013-04-23T14:01:15.733 回答