【问题标题】:Heroku throws OpenURI::HTTPError (403 Forbidden):Heroku 抛出 OpenURI::HTTPError (403 Forbidden):
【发布时间】:2015-04-27 04:27:53
【问题描述】:

我有一个 Rails 4 应用程序向 BackboneJS 前端客户端提供 JSON 数据。后端从 Craigslist 中抓取一些内容并将其作为 JSON 提供给前端。在本地,在开发中,它按预期工作。

在 Heroku 上,应用程序布局确实得到了正确的服务,并且资产似乎加载得很好。直到backboneJS 查询数据以填充适当的视图,应用程序由于OpenURI 错误而失败。

更具体地说,OpenURI 不断返回

OpenURI::HTTPError (403 Forbidden) 

在 Rails 控制器中执行以下行时:

open( "#{clist.url}" )

我花了几个小时尝试在 Stack Overflow 和 Github 上找到的各种“已解决”的解决方案,并且只是尝试查看 Heroku 日志中的其他错误,但无论我尝试哪种建议的“解决方案”,错误仍然存​​在。

到目前为止,我已经尝试了以下建议的解决方案,以及其他几个愚蠢的解决方案:

  • 我的应用程序控制器中必需的 open-uri
  • 在我的 open 方法调用中添加了“用户代理”键
  • 将 clist.url 从“https”更改为“http”以避免重定向

此外,该应用程序非常简单,目前也不需要身份验证。

除了 Stack Overflow 和 github,我在其他地方找不到任何建议的解决方案。任何有关尝试其他调试技巧或建议解决方案的建议的帮助将不胜感激。我对 Heroku 还很陌生,所以仍然熟悉在远程生产引擎上调试这样的问题。

这里是从 Craigslist 获取的相关代码(不要太苛刻地评价我。这个方法的所有/大部分都设置为重构并放入它自己的 Class/Model 中,这是它所属的地方):

def index
    @listings = []

    #Retrieve job listings from Craigslist (see method sync_list below ... )
    @raw_listings = sync_clist

    # filters applied at this point ...
    # and they transform @raw_listings to ...
    # the array @listings

    render json: @listings
end

def sync_clist
    #@search_items = SearchItem.all
    @search_items = SearchItem.all[0..1]
    site = @sites[0]

    # in the Craigslist HTML, the second element in the returned job listing # is the better one to use
    href_idx = 1

    ##### LINE 123 is the next one:
    @search_items.each_with_index do |search_item, idx|
      puts "#{search_item.url.upcase}"

      ##### LINE 125 ... FAILURE_HERE? ***************** 
      html = open( "#{search_item.url}", 'User-Agent' => "Ruby/#{RUBY_VERSION}")
      page = Nokogiri::HTML( html.read, nil, 'utf-8' )
      category_idx = idx % 4
      isNearby_listing = false     #also capture 'nearby' jobs on Craigslist

      page.css( site[:joblist_css] )[0..-2].each_with_index do |listing, i|
        # convert the relative url in the list to a full-url
        locale_idx = idx/@clist_locales.length
        listing_url = listing.css('a')[href_idx]['href']

        # Craigslist only lists the relative path of job urls - relative to the
        # current search location. The 'More Local' items, however, return the
        # full url.
        if !isNearby_listing
          posting_url = site[:protocol] + site[:locales][locale_idx] + "." + site[:host] + listing_url
        else
          posting_url = listing_url
        end

        # Once the appropriate heading is reached, the 'More Local' listings
        # items begin appearing
        if listing.next_sibling.node_name == 'h4'
          isNearby_listing = true
        end

        posting_date = listing.css('time')[0]['datetime']
        job_listing = { :source       => site[:sitename].upcase,
                        :title        => listing.css('a')[href_idx].text,
                        :url          => posting_url,
                        :listing_id   => listing["data-pid"],
                        :location     => @clist_locales[locale_idx],
                        :content      => "",
                        :telecommute  => "",
                        :contract     => "",
                        :pt_ft        => "",
                        :favorite     => false,
                        :posted_date  => posting_date,
                        :category     => @clist_categories[category_idx],
                        :apply_state  => "new"
        }

        @new_listings << job_listing
      end
    end
    @new_listings
  end

这是我的 Heroku 日志的输出,以防有帮助:

```

2015-04-27T03:47:14.611278+00:00 app[web.1]: => Rails 4.0.8 application starting in production on http://0.0.0.0:43688
2015-04-27T03:47:14.611280+00:00 app[web.1]: => Run `rails server -h` for more startup options
2015-04-27T03:47:14.611310+00:00 app[web.1]: Started GET "/" for 24.5.106.52 at 2015-04-27 03:47:14 +0000
2015-04-27T03:47:14.611272+00:00 app[web.1]: => Booting WEBrick
2015-04-27T03:47:14.611281+00:00 app[web.1]: => Ctrl-C to shutdown server
2015-04-27T03:47:14.664777+00:00 app[web.1]:   Rendered app/root.html.erb within layouts/application (0.5ms)
2015-04-27T03:47:14.661735+00:00 app[web.1]: Processing by AppController#root as HTML
2015-04-27T03:47:14.664783+00:00 app[web.1]:   Rendered app/root.html.erb within layouts/application (0.5ms)
2015-04-27T03:47:14.674604+00:00 app[web.1]: Completed 200 OK in 13ms (Views: 12.3ms | ActiveRecord: 0.0ms)
2015-04-27T03:47:14.674612+00:00 app[web.1]: Completed 200 OK in 13ms (Views: 12.3ms | ActiveRecord: 0.0ms)
2015-04-27T03:47:14.611302+00:00 app[web.1]: Started GET "/" for 24.5.106.52 at 2015-04-27 03:47:14 +0000
2015-04-27T03:47:14.661749+00:00 app[web.1]: Processing by AppController#root as HTML
2015-04-27T03:47:15.943141+00:00 heroku[router]: at=info method=GET path="/assets/application-45c34fbd86efe641e061caa3b34737d7.css" host=APPNAME.herokuapp.com request_id=dbf8473e-2880-42f6-8ef4-11e0da7141b4 fwd="24.5.106.52" dyno=web.1 connect=2ms service=73ms status=200 bytes=569692
2015-04-27T03:47:15.944069+00:00 heroku[router]: at=info method=GET path="/assets/application-537f60efd0378faaddaea08875f25055.js" host=APPNAME.herokuapp.com request_id=5c7cf6db-393f-434e-a494-d3664d31a20f fwd="24.5.106.52" dyno=web.1 connect=2ms service=70ms status=200 bytes=965489
2015-04-27T03:47:17.631614+00:00 app[web.1]: Started GET "/posts" for 24.5.106.52 at 2015-04-27 03:47:17 +0000
2015-04-27T03:47:17.631624+00:00 app[web.1]: Started GET "/posts" for 24.5.106.52 at 2015-04-27 03:47:17 +0000
2015-04-27T03:47:17.636842+00:00 app[web.1]: Processing by PostsController#index as JSON
2015-04-27T03:47:17.636831+00:00 app[web.1]: Processing by PostsController#index as JSON
2015-04-27T03:47:17.665568+00:00 app[web.1]: HTTP://SFBAY.CRAIGSLIST.ORG/SEARCH/SOF?QUERY=RAILS
2015-04-27T03:47:18.048174+00:00 heroku[router]: at=info method=GET path="/posts" host=APPNAME.herokuapp.com request_id=a2724fb9-6872-4435-8dfc-0df1b73fb761 fwd="24.5.106.52" dyno=web.1 connect=2ms service=417ms status=500 bytes=330
2015-04-27T03:47:18.042116+00:00 app[web.1]: Completed 500 Internal Server Error in 405ms
2015-04-27T03:47:18.043586+00:00 app[web.1]: OpenURI::HTTPError (403 Forbidden):
2015-04-27T03:47:18.042129+00:00 app[web.1]: Completed 500 Internal Server Error in 405ms
2015-04-27T03:47:18.043590+00:00 app[web.1]:   app/controllers/posts_controller.rb:123:in `each'
2015-04-27T03:47:18.043588+00:00 app[web.1]:   app/controllers/posts_controller.rb:125:in `block in sync_clist'
2015-04-27T03:47:18.043593+00:00 app[web.1]:   app/controllers/posts_controller.rb:123:in `sync_clist'
2015-04-27T03:47:18.043584+00:00 app[web.1]:
2015-04-27T03:47:18.043591+00:00 app[web.1]:   app/controllers/posts_controller.rb:123:in `each_with_index'
2015-04-27T03:47:18.043596+00:00 app[web.1]:
2015-04-27T03:47:18.043594+00:00 app[web.1]:   app/controllers/posts_controller.rb:53:in `index'
2015-04-27T03:47:18.043597+00:00 app[web.1]:
2015-04-27T03:47:18.043602+00:00 app[web.1]:
2015-04-27T03:47:18.043604+00:00 app[web.1]:   app/controllers/posts_controller.rb:125:in `block in sync_clist'
2015-04-27T03:47:18.043603+00:00 app[web.1]: OpenURI::HTTPError (403 Forbidden):
2015-04-27T03:47:18.043606+00:00 app[web.1]:   app/controllers/posts_controller.rb:123:in `each'
2015-04-27T03:47:18.043607+00:00 app[web.1]:   app/controllers/posts_controller.rb:123:in `each_with_index'
2015-04-27T03:47:18.043610+00:00 app[web.1]:   app/controllers/posts_controller.rb:53:in `index'
2015-04-27T03:47:18.043609+00:00 app[web.1]:   app/controllers/posts_controller.rb:123:in `sync_clist'
2015-04-27T03:47:18.043613+00:00 app[web.1]:
2015-04-27T03:47:18.043611+00:00 app[web.1]:

```

【问题讨论】:

  • 嗨,欢迎来到堆栈溢出。您可以编辑您的问题并添加任何相关代码的 sn-ps 吗?例如,您在日志中的 500 错误引用了 posts_controller 的索引操作...这意味着我将开始查看它。
  • 另外,只是检查一下:host=APPNAME.herokuapp.com 是您故意混淆的(顺便说一句,这很好),还是您不小心在其中得到了APPNAME? :)
  • APPNAME 是一种混淆。稍后我会添加相关的控制器代码。
  • 那么是它在posts_controller 中中断的SearchItem.all 行吗? (如果是,你能给我们SearchItem中代码的相关部分吗)(如果不是,你能告诉我们它是哪一行 - 以匹配堆栈跟踪)
  • @Taryn - 感谢您的建议。至少它解释了为什么该应用程序可以在本地运行而不是在 Heroku 上运行。

标签: ruby-on-rails ruby heroku http-status-code-403 open-uri


【解决方案1】:

接受@TarynEast 的建议并在 Heroku 控制台中运行应用程序代码,我改用“net/http”库而不是“open-uri”来检索 Craigslist 网页。 Craigslist 在使用“net/http”时返回以下消息:

"This IP has been automatically blocked.\nIf you have questions, please email: blocks-b1402369961264436@craigslist.org\n"

因此,显然,要么所有 Heroku IP 都已被阻止,要么更有可能只是我的应用程序被阻止,即使我的应用程序在每次站点加载时最多 ping craigslist 8 次。也许这足以阻止它,因为 Craigslist 是一个非常受欢迎的抓取应用程序的目标。无论如何,谜团解开了为什么 403 错误。至少应用仍然可以在本地运行。

[更新:] 根据 Google 的快速搜索,Craigslist 屏蔽了所有 AWS 和 Heroku IP 等。在此处查看 SO 问题:Craigslist blocking Heroku/AWS

【讨论】:

  • @juan8a 你有没有找到其他方法来抓取 Craigslist?
  • @HolgerEdwardWardlowSindbæk - 据我所知,只要执行抓取的服务器的 IP 尚未被禁止(例如您的本地计算机),您就可以抓取它。所有 Heroku 和 AWS(可能是 Google Cloud、Digital Ocean、Microsoft 的云等)都被禁止 AFAIK ......但只要 Craigslist 尚未标记您滥用,您的本地 IP 应该没问题。检查他们的用户指南,确保您没有违反他们的“使用规则”。
  • @juan8a 我知道,因为我在本地做了一些抓取。不过我不想让我自己的 IP 被封禁,所以你知道还有其他没有被封禁的服务吗?!
  • @HolgerEdwardWardlowSindbæk 您必须自己进行搜索才能找到答案。自从我检查这一点以来已经有一段时间了,我发现我有兴趣使用的服务(主要是 AWS 和 Heroku)已经被禁止了。一旦我发现了这一点,我并没有真正寻找其他地方。我可以将服务保留在我的个人计算机上,因为我不打算启动服务供其他人使用。
  • @juan8a Reddit 没有封你?你做了多久?您每天大约点击多少页?!
【解决方案2】:

当我在 Heroku 上托管一个 Rails 应用程序打开 S3 上保存的文件时,我遇到了类似的问题。我得到了同样的错误,因为 URL 错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2013-06-23
    • 2020-09-28
    • 2012-06-11
    • 2018-05-06
    • 1970-01-01
    • 2017-12-10
    相关资源
    最近更新 更多