使用Ruby Mechanize进行Web爬网时,如何避免被网站阻止

时间:2017-09-06 17:54:23

标签: ruby web-crawler mechanize-ruby

我使用单个地址成功地从网站(www.propertyshark.com)抓取建筑数据,但是当我使用循环来刮取多个地址时,我看起来像是被阻止了。有没有解决的办法?仅供参考,根据 robots.txt ,我试图访问的信息不被禁止。

单次运行代码如下:

require 'mechanize'

class PropShark
  def initialize(key,link_key)
    @@key = key
    @@link_key = link_key
  end

  def crawl_propshark_single
    agent = Mechanize.new{ |agent|
      agent.user_agent_alias = 'Mac Safari'
    }
    agent.ignore_bad_chunking = true
    agent.verify_mode = OpenSSL::SSL::VERIFY_NONE

    page = agent.get('https://www.google.com/')
    form = page.forms.first
    form['q'] = "#{@@key}"
    page = agent.submit(form)
    page = form.submit  
    page.links.each do |link|
      if link.text.include?("#{@@link_key}")  
        if link.text.include?("PropertyShark")
          property_page = link.click
        else
          next
        end

        if property_page
          data_value = property_page.css("div.cols").css("td.r_align")[4].text # <--- error points to these commands
          data_name = property_page.css("div.cols").css("th")[4].text
          @result_hash["#{data_name}"] = data_value
        else
          next
        end
      end 
    end

    return @result_hash
  end
end #endof: class PropShark

# run
key = '41 coral St, Worcester, MA 01604 propertyshark'
key_link = '41 Coral Street'
spider = PropShark.new(key,key_link)
puts spider.crawl_propshark_single

我收到以下错误但在一两个小时内错误消失了:

undefined method `text' for nil:NilClass (NoMethodError)

当我使用上述代码使用循环时,我通过在地址之间加sleep 80来延迟进程。

2 个答案:

答案 0 :(得分:3)

在您做任何其他事情之前,您应该做的第一件事就是联系网站所有者。现在,你可以在过于激进和illegal之间的任何地方解释你的行为。正如其他人所指出的,业主可能不希望你刮网站。或者,它们可能具有可用于此特定事物的API或产品Feed。无论哪种方式,如果您要依赖本网站的产品,您可能需要考虑与他们玩得很好。

话虽如此,你正在通过他们的网站浏览一家中国商店的大象的优雅。在异常的用户代理,来自单个IP的异常使用模式以及请求之间可预测的延迟之间,您已经完全破坏了封面。考虑通过网站采取更有机的路径,更加自然的仿真延迟。此外,你应该伪装你的使用者,或者让它变得非常明显(Josh的大坏刮刀)。您甚至可以考虑使用像Selenium这样的东西,它使用真正的浏览器而不是Mechanize来提供更少的提示。

您还可以考虑添加更强大的错误处理。也许该网站处于过载(或其他),并且您正在解析的页面不是所需的页面,而是一些随机错误页面。您可以通过简单的重试来获取有问题的数据。在刮擦时,功能不良或效率低下的站点可能会像故意刮擦保护一样成为障碍。

如果这些都不起作用,您可以考虑设置精心设计的代理数组,但此时您可以更好地使用当前存在的众多在线Webscraping / API创建/数据提取服务之一。它们相当便宜,已经完成了上面讨论的所有内容,还有更多。

答案 1 :(得分:2)

很可能没有什么能阻挡你。正如你所指出的那样

property_page.css("div.cols").css("td.r_align")[4].text

是问题所在。因此,让我们专注于那一行代码。

首先说明您的列第一次为columns = [1,2,3,4,5],然后rows[4]将返回5(索引为4的元素)。

不是为了好玩,我们假设您的列的下一行是columns = ['a','b','c','d'],然后rows[4]会返回nil,因为第四个索引没有任何内容。

这似乎是你的情况,有时有5列,有时没有。因此导致nil.text和您收到的错误