Nokogiri 在函数中抛出异常但不在函数外

Nokogiri Throwing Exception in Function but not outside of Function

我是 Ruby 的新手,正在使用 Nokogiri 解析 html 网页。函数到达行时会抛出错误:

currentPage = Nokogiri::HTML(open(url))

我已经验证了函数的输入,url 是一个带有网址的字符串。我之前提到的那行在函数外部使用时完全按照预期工作,但在函数内部则不然。当它到达函数内部的那一行时,抛出以下错误:

WebCrawler.rb:25:in `explore': undefined method `+@' for #<Nokogiri::HTML::Document:0x007f97ea0cdf30> (NoMethodError)
from WebCrawler.rb:43:in `<main>'

下面粘贴了有问题的行所在的函数。

def explore(url)
    if CRAWLED_PAGES_COUNTER > CRAWLED_PAGES_LIMIT
            return
    end
    CRAWLED_PAGES_COUNTER++

    currentPage = Nokogiri::HTML(open(url))
    links = currentPage.xpath('//@href').map(&:value)

    eval_page(currentPage)

    links.each do|link|
            puts link
            explore(link)
    end
end

这是完整的程序(不会太长):

require 'nokogiri'
require 'open-uri'

#Crawler Params
START_URL = "https://en.wikipedia.org"
CRAWLED_PAGES_COUNTER = 0
CRAWLED_PAGES_LIMIT = 5

#Crawler Functions
def explore(url)
    if CRAWLED_PAGES_COUNTER > CRAWLED_PAGES_LIMIT
            return
    end
    CRAWLED_PAGES_COUNTER++

    currentPage = Nokogiri::HTML(open(url))
    links = currentPage.xpath('//@href').map(&:value)

    eval_page(currentPage)

    links.each do|link|
            puts link
            explore(link)
    end
end

def eval_page(page)
    puts page.title
end

#Start Crawling


explore(START_URL)
require 'nokogiri'
require 'open-uri'

#Crawler Params
$START_URL = "https://en.wikipedia.org"
$CRAWLED_PAGES_COUNTER = 0
$CRAWLED_PAGES_LIMIT = 5

#Crawler Functions
def explore(url)
    if $CRAWLED_PAGES_COUNTER > $CRAWLED_PAGES_LIMIT
            return
    end
    $CRAWLED_PAGES_COUNTER+=1

    currentPage = Nokogiri::HTML(open(url))
    links = currentPage.xpath('//@href').map(&:value)

    eval_page(currentPage)

    links.each do|link|
            puts link
            explore(link)
    end
end

def eval_page(page)
    puts page.title
end

#Start Crawling


explore($START_URL)

只是为了给你一些东西来构建,这是一个简单的蜘蛛,它只收获和访问链接。修改它来做其他事情会很容易。

require 'nokogiri'
require 'open-uri'
require 'set'

BASE_URL = 'http://example.com'
URL_FORMAT = '%s://%s:%s'
SLEEP_TIME = 30 # in seconds

urls = [BASE_URL]
last_host = BASE_URL
visited_urls = Set.new
visited_hosts = Set.new

until urls.empty?
  this_uri = URI.join(last_host, urls.shift)
  next if visited_urls.include?(this_uri)

  puts "Scanning: #{this_uri}"

  doc = Nokogiri::HTML(this_uri.open)
  visited_urls << this_uri

  if visited_hosts.include?(this_uri.host)
    puts "Sleeping #{SLEEP_TIME} seconds to reduce server load..."
    sleep SLEEP_TIME
  end

  visited_hosts << this_uri.host

  urls += doc.search('[href]').map { |node|
    node['href'] 
  }.select { |url|
    extension = File.extname(URI.parse(url).path)
    extension[/\.html?$/] || extension.empty?
  }

  last_host = URL_FORMAT % [:scheme, :host, :port].map{ |s| this_uri.send(s) }
  puts "#{urls.size} URLs remain."
end

它:

  • 适用于 http://example.com。该网站专为实验而设计和指定。
  • 检查以前是否访问过某个页面并且不会再次扫描它。这是一种天真的检查,会被包含查询或顺序不一致的查询的 URL 所愚弄。
  • 检查网站以前是否访问过,如果访问过,则自动限制页面检索。它可能被别名所愚弄。
  • 检查页面是否以“.htm”、“.html”结尾或没有扩展名。忽略其他任何内容。

编写工业强度蜘蛛的实际代码要复杂得多。 Robots.txt 文件需要被尊重,弄清楚如何处理通过 HTTP 超时或 JavaScript 重定向重定向到其他页面的页面是一项有趣的任务,处理格式错误的页面是一个挑战....