1

我正在阅读使用 ruby​​ 构建域爬虫方法的人的代码。我是递归概念的新手,无法理解如何阅读他们的代码。

代码:

def crawl_domain(url, page_limit = 100)
  return if @already_visited.size == page_limit                # [1]
  url_object = open_url(url)
  return if url_object == nil                                  # [2]
  parsed_url = parse_url(url_object)
  return if parsed_url == nil                                  # [3]
  @already_visited[url]=true if @already_visited[url] == nil
  page_urls = find_urls_on_page(parsed_url, url)
  page_urls.each do |page_url|
    if urls_on_same_domain?(url, page_url) and @already_visited[page_url] == nil
      crawl_domain(page_url)
    end
  end
end

问题:

  1. 连续return语句的组合是什么意思?
  2. 在第 [1] 行,如果 @already_visited 的大小page_limit 不同,程序是否会跳出 crawl_domain 方法并跳过其余代码?
  3. 如果@already_visited 的大小page_limit 相同,是否在设置后继续下一个return 语句url_object = open_url(url)

提前感谢您的帮助!

资料来源: http ://www.skorks.com/2009/07/how-to-write-a-web-crawler-in-ruby/

4

3 回答 3

3

忘记网络爬虫。考虑如何使用递归来添加构成数组的数字:

arr = [1, 2, 3, 4]
def sum(array)
  # ??
end
puts sum(arr) #=> 10, please

假装问题已经解决。(所有递归都取决于假装这个。)然后sum([1, 2, 3, 4])1 + sum([2, 3, 4]),并且通常sum对于任何数组,都是第一个元素加上sum数组的其余部分。在 ruby​​ 中,将数组拆分为第一个数组和剩余数组的方法是shift; 调用shift返回数组的第一个元素并将其从数组中删除。所以我们可以写:

arr = [1, 2, 3, 4]
def sum(array)
  return array.shift + sum(array)
end
puts sum(arr)

看哪,递归解决方案!然而,有一个问题:我们永远递归(或者,至少,直到遇到某种错误)。在所有递归中,在递归之前在退化情况下放置某种“停止”是至关重要的。在我们的情况下,这种退化的情况是什么?当数组为空时!(最终会是这样,因为每次sum调用都会从数组中删除一个元素。)对于一个空数组,显然sum是零。所以:

arr = [1, 2, 3, 4]
def sum(array)
  return 0 unless array.length > 0
  return array.shift + sum(array)
end
puts sum(arr)

结束。

您的网络爬虫类似。我们将递归爬取当前页面的每个子级别,但首先我们有一些“停止”(return语句)以防止在各种退化情况下陷入错误情况。(在网络爬虫的情况下,不需要检查当前页面是否真的子级别,因为如果没有,each将什么都不做,我们也不会递归。)

于 2013-04-01T03:52:04.613 回答
2

对递归感到困惑?阅读本书:

http://mitpress.mit.edu/sicp/

您将成为一个更好的程序员,并且您将永远递归蓝线。

于 2013-04-01T03:27:34.423 回答
1
于 2017-05-03T23:50:47.103 回答