7

我编写了一个脚本,它将遍历我们数据库中的所有客户,验证他们的网站 URL 是否有效,并尝试在他们的主页上找到一个 Twitter 链接。我们有超过 10,000 个 URL 需要验证。在验证了 url 的一小部分之后,我们开始为每个 URL 获取 getaddrinfo 错误。

这是抓取单个 URL 的代码副本:

def scrape_url(url) 
  url_found = false 
  twitter_name = nil 

  begin 
    agent = Mechanize.new do |a| 
      a.follow_meta_refresh = true 
    end 

    agent.get(normalize_url(url)) do |page| 
      url_found = true 
      twitter_name = find_twitter_name(page) 
    end 

    @err << "[#{@current_record}] SUCCESS\n" 
  rescue Exception => e 
    @err << "[#{@current_record}] ERROR (#{url}): " 
    @err << e.message 
    @err << "\n" 
  end 

  [url_found, twitter_name] 
end

注意:我还运行了此代码的一个版本,它创建了一个 Mechanize 实例,该实例在所有对 scrape_url 的调用中共享。它以完全相同的方式失败了。

当我在 EC2 上运行它时,它几乎正好通过了 1,000 个 URL,然后为剩余的 9,000+ 返回此错误:

getaddrinfo: Temporary failure in name resolution

注意,我尝试过使用亚马逊的 DNS 服务器和谷歌的 DNS 服务器,认为这可能是一个合法的 DNS 问题。在这两种情况下,我得到了完全相同的结果。

然后,我尝试在本地 MacBook Pro 上运行它。在为其余记录返回此错误之前,它仅通过了大约 250 次:

getaddrinfo: nodename nor servname provided, or not known

有谁知道我怎样才能让脚本通过所有记录?

4

2 回答 2

10

我找到了解决方案。Mechanize 使连接保持打开状态并依靠 GC 来清理它们。在某个点之后,有足够的打开连接,无法建立额外的出站连接来进行 DNS 查找。这是导致它工作的代码:

agent = Mechanize.new do |a| 
  a.follow_meta_refresh = true
  a.keep_alive = false
end

通过将keep_alive 设置为false,连接会立即关闭并清理。

于 2012-11-03T20:59:55.107 回答
0

看看这是否有帮助:

agent.history.max_size = 10

它将防止历史使用过多的内存

于 2012-11-02T00:07:43.277 回答