9.1 爬虫及爬行方式

来源:互联网 发布:数据查询网站源码 编辑:程序博客网 时间:2024/04/30 01:56
  • Web 机器人(Web robot):自活跃(self-animating)用户代理,是能够在无需人类干预的情况下自动进行一系列 Web 事务处理的软件程序。
  • 很多机器人会从一个 Web 站点逛到另一个 Web 站点,获取内容,跟踪超链,并对它们找到的数据进行处理。根据这些机器人自动探查 Web 站点的方式,人们为它们起了一些各具特色的名字,比如“爬虫”、“蜘蛛”、“蠕虫”以及“机器人”等,就好像它们都有自己的头脑一样。
  • Web 爬虫:是一种机器人,它们会递归地对各种信息性 Web 站点进行遍历,获取第一个 Web 页面,然后获取那个页面指向的所有 Web 页面,然后是那些页面指向的所有 Web 页面,依此类推。递归地追踪这些 Web 链接的机器人会沿着 HTML 超链创建的网络“爬行”,所以将其称为爬虫(crawler)或蜘蛛(spider)。
  • 因特网搜索引擎使用爬虫在 Web 上游荡,并把它们碰到的文档全部拉回来。然后对这些文档进行处理,形成一个可搜索的数据库,以便用户查找包含了特定单词的文档。

1. 根集

  • 爬虫开始访问的 URL 初始集合被称作根集(root set)。
  • 挑选根集时,应该从足够多不同的站点中选择 URL,这样,爬遍所有的链接才能最终到达大部分你感兴趣的 Web 页面。
  • 没有哪一个文档最终可以链接到所有其他文档上去。
  • 根集中并不需要有很多页面,就可以涵盖一大片 Web 结构。下图中,要抵达所有页面,根集中只需要有 A、G 和 S 就行了。
    这里写图片描述
  • 通常,一个好的根集会包括一些大的流行 Web 站点、一个新创建页面的列表和一个不经常被链接的无名页面列表。
  • 很多大规模的爬虫产品,比如因特网搜索引擎使用的那些爬虫,都为用户提供了向根集中提交新页面或无名页面的方式。这个根集会随时间推移而增长,是所有新爬虫的种子列表。

2. 链接的提取以及相对链接的标准化

  • 爬虫在 Web 上移动时,会不停地对 HTML 页面进行解析。它要对所解析的每个页面上的 URL 链接进行分析,并将这些链接添加到需要爬行的页面列表中去。随着爬虫的前进,当其发现需要探查的新链接时,这个列表常常会迅速地扩张,直到已经对 Web 空间进行了彻底的探查为止,这时爬虫就会到达一个不再发现新链接的状态了。
  • 爬虫要通过简单的 HTML 解析,将这些链接提取出来,并将相对 URL 转换为绝对形式。转换方式见2.3 URL 快捷方式

3. 避免环路的出现

  • 机器人在 Web 上爬行时,要特别小心不要陷入循环,或环路(cycle)之中。
    这里写图片描述
  • 机器人必须知道它们到过何处,以避免环路的出现。环路会造成机器人陷阱,这些陷阱会暂停或减缓机器人的爬行进程。

4. 循环与复制

  • 为何环路对爬虫来说是有害的:
    • 它们会使爬虫陷入可能会将其困住的循环之中。循环会使未经良好设计的爬虫不停地兜圈子,把所有时间都耗费在不停地获取相同的页面上。爬虫会消耗掉很多网络带宽,可能完全无法获取任何其他页面了。
    • 爬虫不断地获取相同的页面时,另一端的 Web 服务器也在遭受着打击。如果爬虫与服务器连接良好,它就会击垮 Web 站点,阻止所有真实用户访问这个站点。这种拒绝服务是可以作为法律诉讼理由的。
    • 即使循环自身不是什么问题,爬虫也是在获取大量重复的页面 [通常被称为“dups”(重复),以便与“loops”(循环)押韵]。爬虫应用程序会被重复的内容所充斥,这样应用程序就会变得毫无用处。返回数百份完全相同页面的因特网搜索引擎就是一个这样的例子。

5. 判断爬虫到过哪里

  • 由于 URL 的数量巨大,所以,要使用复杂的数据结构以便快速判定哪些 URL 是曾经访问过的。数据结构在访问速度和内存使用方面都应该是非常高效的。
  • 大规模 Web 爬虫对其访问过的地址进行管理时使用的一些有用的技术:
    • 树和散列表
      复杂的机器人可能会用搜索树或散列表来记录已访问的 URL。这些是加速 URL 查找的软件数据结构。
    • 有损的存在位图
      为了减小空间,一些大型爬虫会使用有损数据结构,比如存在位数组(presence bit array)。用一个散列函数将每个 URL 都转换成一个定长的数字,这个数字在数组中有个相关的“存在位”。爬行过一个 URL 时,就将相应的“存在位”置位。如果存在位已经置位了,爬虫就认为已经爬行过那个 URL 了。
      由于 URL 的潜在数量是无限的,而存在位数组中的比特数是有限的,所以有出现冲突的可能——两个 URL 可能会映射到同一个存在位上去。出现这种情况时,爬虫会错误地认为它已经爬行过某个实际未爬行过的页面了。在实际应用中,使用大量的存在位就可以使这种情况极少发生。产生冲突的后果就是爬虫会忽略某个页面。
    • 检查点
      一定要将已访问 URL 列表保存到硬盘上,以防机器人程序崩溃。
    • 分类
      随着 Web 的扩展,在一台计算机上通过单个机器人来完成爬行就变得不太现实了。那台计算机可能没有足够的内存、磁盘空间、计算能力,或网络带宽来完成爬行任务。
      有些大型 Web 机器人会使用机器人“集群”,每个独立的计算机是一个机器人,以汇接方式工作。为每个机器人分配一个特定的 URL“片区”,由其负责爬行。这些机器人配合工作,爬行整个 Web。机器人个体之间可能需要相互通信,来回传送URL,以覆盖出故障的对等实体的爬行范围,或协调其工作。

6. 别名与机器人环路

  • 别名:如果两个 URL 看起来不一样,但实际指向的是同一资源,就称 这两个 URL 互为“别名”。
  • 由于 URL“别名”的存在,即使使用了正确的数据结构,有时也很难分辨出以前是否访问过某个页面。
  • 别名有可能会造成机器人环路的产生。
  • 不同 URL 指向同一资源的情况:
第一个URL 第二个URL 什么时候是别名 a http://www.foo.com/bar.html http://www.foo.com:80/bar.html 默认端口为 80 b http://www.foo.com/~fred http://www.foo.com/%7Ffred %7F 与 ~ 相同 c http://www.foo.com/x.html#early http://www.foo.com/x.html#middle 标签并没有修改页面内容 d http://www.foo.com/readme.htm http://www.foo.com/README.HTM 服务器是大小写无关的 e http://www.foo.com/ http://www.foo.com/index.html 默认页面为 index.html f http://www.foo.com/index.html http://209.231.87.45/index.html www.foo.com 使用这个 IP 地址

7. 规范化 URL

  • 大多数 Web 机器人都试图通过将 URL“规范化”为标准格式来消除上面那些显而易见的别名。
  • 规范化 URL 步骤:
    1. 如果没有指定端口的话,就向主机名中添加“:80”。
    2. 将所有转义符 %xx 都转换成等价字符。
    3. 删除 # 标签。
  • 这些步骤可以消除上表中a~c的别名问题,但如果不知道特定 Web 服务器的相关信息,机器人就没什么好办法来避免上表中d~f的问题了。
    • 机器人需要知道 Web 服务器是否是大小写无关的才能避免 d 中的别名问题。
    • 机器人需要知道 Web 服务器上这个目录下的索引页面配置才能知道 e 中的情况是否是别名。
    • 即使机器人知道 f 中的主机名和 IP 地址都指向同一台计算机,它也还要知道 Web 服务器是否配置为进行(参见第 5 章)虚拟主机操作,才能知道这个 URL 是不是别名。
  • URL 规范化可以消除一些基本的语法别名,但机器人还会遇到其他的、将 URL 转换为标准形式也无法消除的 URL 别名。

8. 文件系统连接环路

  • 文件系统中的符号连接会造成特定的潜在环路,因为它们会在目录层次深度有限的情况下,造成深度无限的假象。
  • 符号连接环路通常是由服务器管理员的无心错误造成的,但“邪恶的网管”也可能会恶意地为机器人制造这样的陷阱。
  • 下图中,显示了两个文件系统,a 中 subdir 是个普通的目录,b 中 subdir 是个指回到“/”的符号连接。在这两个图中,都假设文件 /index.html 中包含 了一个指向文件 subdir/index.html 的超链。最终 b 会导致环路:
    这里写图片描述

9. 动态虚拟 Web 空间

  • 恶意网管可能会有意创建一些复杂的爬虫循环来陷害那些无辜的、毫无戒备的机器人。尤其是,发布一个看起来像普通文件,实际上却是网关应用程序的 URL 是很容易的。这个应用程序可以在传输中构造出包含了到同一服务器上虚构 URL 链接的 HTML。请求这些虚构的 URL 时,这个邪恶的服务器就会捏造出一个带有新的虚构 URL 的新 HTML 页面来。
  • 即使这个恶意 Web 服务器实际上并不包含任何文件,它也可以通过无限虚拟的 Web 空间将可怜的机器人带入爱丽丝漫游仙境之旅。更糟的是,每次的 URL 和 HTML 看起来都有很大的不同,机器人很难检测到环路。
  • 恶意的动态 Web 空间示例:
    这里写图片描述
  • 更常见的情况是,那些没有恶意的网管们可能会在无意中通过符号连接或动态内容构造出爬虫陷阱。

10. 避免循环和重复

  • 没有什么简单明了的方式可以避免所有的环路。实际上,经过良好设计的机器人中要包含一组试探方式,以避免环路的出现。
  • 总的说来,爬虫的自动化程度越高(人为的监管越少),越可能陷入麻烦之中。机器人的实现者需要做一些取舍——这些试探方式有助于避免问题的出现,但你可能会终止扫描那些看起来可疑的有效内容,因此这种方式也是“有损失”的。
  • 避免循环和重复的一些方法:
    • 规范化 URL
      将 URL 转换为标准形式以避免语法上的别名。
    • 广度优先的爬行
      每次爬虫都有大量潜在的 URL 要去爬行。以广度优先的方式来调度 URL 去访问 Web 站点,就可以将环路的影响最小化。即使碰到了机器人陷阱,也可以在回到环路中获取的下一个页面之前,从其他 Web 站点中获取成百上千的页面。如果采用深度优先方式,一头扎到单个站点中去,就可能会跳入环路,永远无法访问其他站点。
      总之,广度优先搜索是个好方法,这样可以更均匀地分配请求,而不是都压到任意一台服务器上去。这样可以帮助机器人将用于一台服务器的资源保持在最低水平。
    • 节流
      限制一段时间内机器人可以从一个 Web 站点获取的页面数量。如果机器人跳进了一个环路,试图不断地访问某个站点的别名,也可以通过节流来限制重复的页面总数和对服务器的访问总数。
    • 限制 URL 的大小
      机器人可能会拒绝爬行超出特定长度(通常是 1KB)的 URL。如果环路使 URL 的长度增加,长度限制就会最终终止这个环路。有些 Web 服务器在使用长 URL 时会失败,因此,被 URL 增长环路困住的机器人会使某些 Web 服务器崩溃。这会让网管错误地将机器人当成发起拒绝服务攻击的攻击者。
      要小心,这种技术肯定会让你错过一些内容。现在很多站点都会用 URL 来管理用户的状态(比如,在一个页面引用的 URL 中存储用户 ID)。用 URL 长度来限制爬虫可能会带来些麻烦;但如果每当请求的 URL 达到某个特定长度时,都记录一次错误的话,就可以为用户提供一种检查某特定站点上所发生情况的方法。
    • URL/ 站点黑名单
      维护一个与机器人环路和陷阱相对应的已知站点及 URL 列表,然后像躲避瘟疫一样避开它们。发现新问题时,就将其加入黑名单。
      这就要求有人工进行干预。但现在很多大型爬虫产品都有某种形式的黑名单,用于避开某些存在固有问题或者有恶意的站点。还可以用黑名单来避开那些对爬行大惊小怪的站点。
    • 模式检测
      文件系统的符号连接和类似的错误配置所造成的环路会遵循某种模式;比如,URL 会随着组件的复制逐渐增加。有些机器人会将具有重复组件的 URL 当作潜在的环路,拒绝爬行带有多于两或三个重复组件的 URL。
      重复并不都是立即出现的(比如,“/subdir/subdir/subdir…”)。有些环路周期可能为2或其他间隔,比如“/subdir/images/subdir/images/subdir/images/…”。有些机器人会查找具有几种不同周期的重复模式。
    • 内容指纹
      一些更复杂的 Web 爬虫会使用指纹这种更直接的方式来检测重复。使用内容指纹的机器人会获取页面内容中的字节,并计算出一个校验和(checksum)。这个校验和是页面内容的压缩表示形式。如果机器人获取了一个页面,而此页面的校验和它曾经见过,它就不会再去爬行这个页面的链接了——如果机器人以前见过页面的内容,它就已经爬行过页面上的链接了。
      必须对校验和函数进行选择,以求两个不同页面拥有相同校验和的几率非常低。MD5 这样的报文摘要函数就常被用于指纹计算。
      有些 Web 服务器会在传输过程中对页面进行动态的修改,所以有时机器人会在校验和的计算中忽略 Web 页面内容中的某些部分,比如那些嵌入的链接。而且,无论定制了什么页面内容的动态服务器端包含(比如添加日期、访问计数等)都可能会阻碍重复检测。
    • 人工监视
      机器人最终总会陷入一个采用任何技术都无能为力的困境。设计所有产品级机器人时都要有诊断和日志功能,这样人类才能很方便地监视机器人的进展,如果发生了什么不寻常的事情就可以很快收到警告。