Wget手册中的下一句话引起了我的注意

wget --spider --force-html -i bookmarks.html

This feature needs much more work for Wget to get close to the functionality of real web spiders.

我发现以下代码行与 wget 中的蜘蛛选项相关。

src/ftp.c
780:      /* If we're in spider mode, don't really retrieve anything.  The
784:      if (opt.spider)
889:  if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1227:      if (!opt.spider)
1239:      if (!opt.spider)
1268:      else if (!opt.spider)
1827:          if (opt.htmlify && !opt.spider)

src/http.c
64:#include "spider.h"
2405:  /* Skip preliminary HEAD request if we're not in spider mode AND
2407:  if (!opt.spider
2428:      if (opt.spider && !got_head)
2456:      /* Default document type is empty.  However, if spider mode is
2570:           * spider mode.  */
2571:          else if (opt.spider)
2661:              if (opt.spider)

src/res.c
543:  int saved_sp_val = opt.spider;
548:  opt.spider       = false;
551:  opt.spider       = saved_sp_val;  

src/spider.c
1:/* Keep track of visited URLs in spider mode.
37:#include "spider.h"
49:spider_cleanup (void)

src/spider.h
1:/* Declarations for spider.c

src/recur.c
52:#include "spider.h"
279:      if (opt.spider)
366:              || opt.spider /* opt.recursive is implicitely true */
370:             (otherwise unneeded because of --spider or rejected by -R) 
375:                   (opt.spider ? "--spider" : 
378:                     (opt.delete_after || opt.spider
440:      if (opt.spider) 

src/options.h
62:  bool spider;           /* Is Wget in spider mode? */

src/init.c
238:  { "spider",           &opt.spider,            cmd_boolean },

src/main.c
56:#include "spider.h"
238:    { "spider", 0, OPT_BOOLEAN, "spider", -1 },
435:       --spider                  don't download anything.\n"),
1045:  if (opt.recursive && opt.spider)

我想看到代码中的差异,而不是抽象地。我喜欢代码示例。

网络蜘蛛与 Wget 蜘蛛有何不同 在代码中?

有帮助吗?

解决方案

真正的蜘蛛需要大量的工作

为整个 WWW 编写一个爬虫是一项艰巨的任务 --- 您必须注意许多“小细节”,例如:

  • 每台蜘蛛计算机应并行接收来自数千台服务器的数据,以便有效利用连接带宽。(异步套接字 I/O)。
  • 您需要多台计算机并行爬行才能覆盖 WWW 上的大量信息(集群;划分工作)
  • 您需要对蜘蛛抓取的网站保持礼貌:
    • 尊重 robots.txt 文件。
    • 不要太快获取大量信息:这会使服务器超载。
    • 不要获取您确实不需要的文件(例如iso 磁盘映像;用于软件下载的 tgz 软件包...)。
  • 您必须处理 cookie/会话 ID:许多站点将唯一的会话 ID 附加到 URL 来识别客户端会话。每次您到达该站点时,您都​​会获得一个新的会话 ID 和一个新的虚拟页面世界(具有相同的内容)。由于这些问题,早期的搜索引擎忽略了动态内容。现代搜索引擎已经了解了问题是什么以及如何处理它们。
  • 您必须检测并忽略有问题的数据:提供看似无限量数据的连接或速度太慢而无法完成的连接。
  • 除了以下链接之外,您可能还想解析 站点地图 获取页面的 URL。
  • 您可能想要评估哪些信息对您来说很重要并且经常更改,以便比其他页面更频繁地刷新。笔记:整个万维网的蜘蛛接收大量数据——您需要为该带宽付费。您可能想要使用 HTTP HEAD 请求来猜测页面是否已更改。
  • 除了接收之外,您还需要处理信息并存储它。谷歌建立索引,列出每个单词包含它的页面。您可能需要单独的存储计算机和基础设施来连接它们。传统的关系数据库无法满足存储/索引整个 WWW 的数据量和性能要求。

这是一项繁重的工作。但如果您的目标比阅读整个 WWW 更温和,您可以跳过某些部分。如果您只想下载 wiki 等的副本。您可以了解 wget 的规格。

笔记:如果您不相信这需要这么多工作,您可能想了解 Google 如何重新发明大部分计算轮(在基本 Linux 内核之上)来构建优秀的蜘蛛。即使你抄了很多捷径,这也是很多工作。

让我就三点补充一些技术性评论

并行连接/异步套接字通信

您可以在并行进程或线程中运行多个蜘蛛程序。但您需要大约 5000-10000 个并行连接才能充分利用您的网络连接。而且如此数量的并行进程/线程会产生过多的开销。

更好的解决方案是异步输入/输出:通过以非阻塞模式打开套接字,在一个线程中处理大约 1000 个并行连接,并使用 epoll 或 select 只处理那些已接收数据的连接。从Linux内核2.4开始,Linux对可扩展性的支持(我也建议大家研究一下内存映射文件)在以后的版本中不断完善。

笔记:使用异步 I/O 比使用“快速语言”更有帮助:用 Perl 编写一个用于 1000 个连接的 epoll 驱动进程比用 C 编写的运行 1000 个进程要好。如果你做得正确,你可以用 Perl 编写的进程使 100Mb 连接饱和。

从原来的答案来看: 这种方法的缺点是您必须自己以异步形式实现 HTTP 规范(我不知道有一个可重用的库可以做到这一点)。使用更简单的 HTTP/1.0 协议比现代 HTTP/1.1 协议更容易做到这一点。无论如何,您可能不会从普通浏览器的 HTTP/1.1 的优势中受益,因此这可能是节省一些开发成本的好地方。

五年后编辑:如今,有很多免费/开源技术可以帮助您完成这项工作。我个人比较喜欢异步 http实现节点.js ---它为您节省了上面原始段落中提到的所有工作。当然,今天还有许多模块可随时用于您的蜘蛛中所需的其他组件。但请注意,第三方模块的质量可能会有很大差异。你必须检查你使用的任何东西。 [老化信息:] 最近,我使用node.js编写了一个spider,我发现npm模块用于HTML处理、链接和数据提取的可靠性不足。对于这项工作,我将此处理“外包”给用另一种编程语言编写的进程。但事情正在迅速变化,当您阅读此评论时,这个问题可能已经成为过去......

将工作划分到多个服务器上

一台计算机无法跟上整个万维网的爬行速度。您需要将工作分布到多个服务器上并在它们之间交换信息。我建议为每个服务器分配某些“域名范围”:保存一个域名中央数据库,并引用蜘蛛计算机。

批量提取接收到的网页的URL:根据域名对它们进行排序;删除重复项并将其发送到负责的蜘蛛计算机。在该计算机上,保留已获取的 URL 的索引并获取剩余的 URL。

如果您在每台蜘蛛计算机上保留一个等待获取的 URL 队列,则不会出现性能瓶颈。但要实现这一点需要相当多的编程。

阅读标准

我提到了几个标准(HTTP/1.x、Robots.txt、Cookies)。花点时间阅读并实施它们。如果您只是遵循您所知道的站点示例,您将会犯错误(忘记与您的示例不相关的标准部分),并给那些使用这些附加功能的站点带来麻烦。

阅读 HTTP/1.1 标准文档是一件痛苦的事情。但所有的小细节都被添加到其中,因为有人确实需要这些小细节并且现在使用它。

其他提示

我不知道到底是什么注释的原作者所指的,但我可以猜测的wget是慢如蜘蛛,因为它似乎只使用执行(单线程至少由你出什么)。

“真正的”蜘蛛例如 Heritrix的使用大量的并行性和花样来优化他们的爬行速度,而同时很好的网站,他们爬行。这通常意味着以1每秒(或左右)的速率限制命中一个站点,并且在同一时间抓取多个网站。

再次,这是一切只是猜测基于我所知道的一般的蜘蛛,和你贴什么在这里。

不幸的是,许多更知名的“真正的”网络蜘蛛都是闭源的,而且实际上是闭源二进制的。然而 wget 缺少一些基本技术:

  • 并行性;如果不一次检索多个页面,您将永远无法跟上整个网络的步伐
  • 优先顺序;有些页面对蜘蛛来说比其他页面更重要
  • 速率限制;如果您继续尽快下拉页面,您很快就会被禁止
  • 保存到本地文件系统以外的其他位置;网络足够大,单个目录树无法容纳它
  • 定期重新检查页面,无需重新启动整个流程;实际上,对于真正的蜘蛛,您需要经常重新检查“重要”页面的更新,而不太有趣的页面可能会持续数月。

还可以使用各种其他输入,例如站点地图等。重点是,wget 并不是为了抓取整个网络而设计的,而且它并不是真正可以在一个小代码示例中捕获的东西,因为它是所使用的整个整体技术的问题,而不是任何单个小子例程错误的问题为了任务。

我不会详细介绍如何抓取互联网,我认为 wget 评论是关于抓取一个网站,这仍然是一个严峻的挑战。

  • 作为蜘蛛,您需要弄清楚何时停止,而不是仅仅因为 URL 发生变化(例如 date=1/1/1900 到 1/2/1900 等)而进行递归爬行
  • 解决 URL 重写的更大挑战(我不知道谷歌或任何其他人如何处理这个问题)。爬行足够多但又不能太多是一个很大的挑战。如何自动识别带有一些随机参数和内容随机变化的 URL Rewrite?
  • 您需要至少在一定程度上解析 Flash / Javascript
  • 你需要考虑一些疯狂的 HTTP 问题,比如 根据 标签。考虑到大多数网站都不是 XHTML 并且浏览器的语法非常灵活,即使解析 HTML 也不容易。

我不知道 wget 中实现或考虑了多少这些内容,但您可能想看看 httrack 以了解此任务的挑战。

我很乐意为您提供一些代码示例,但这是一项艰巨的任务,一个像样的蜘蛛大约需要 5000 loc 没有第三方库.

+ 其中一些已经由 @yaakov-belch 解释过,所以我不会再输入它们

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top