2011-08-03 9 views
31

私はURLを取得しており、HTTP GETを使用してページにクエリを渡しています。最新のフレーバー(net/http)では、スクリプトが302応答を超えないということが起こります。私はいくつかの異なるソリューションを試しました。 HTTPClient、net/http、Rest-Client、Patron ...Ruby - net/http - リダイレクトの後

そのページの属性タグを検証するには、最後のページに進む必要があります。リダイレクトは、モバイルユーザーエージェントがモバイルビューにリダイレクトするページに当たることによるものであり、したがってヘッダー内のモバイルユーザーエージェントです。ここに私のコードは今日のようです:

require 'uri' 
require 'net/http' 

class Check_Get_Page 

    def more_http 
     url = URI.parse('my_url') 
     req, data = Net::HTTP::Get.new(url.path, { 
     'User-Agent' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5' 
     }) 
     res = Net::HTTP.start(url.host, url.port) {|http| 
     http.request(req) 
      } 
     cookie = res.response['set-cookie'] 
     puts 'Body = ' + res.body 
     puts 'Message = ' + res.message 
     puts 'Code = ' + res.code 
     puts "Cookie \n" + cookie 
    end 

end 

m = Check_Get_Page.new 
m.more_http 

私は何か提案は大歓迎です!

+0

私は複数のリダイレクト後の最終的なURLを取得するには、[final_redirect_url](https://rubygems.org/gems/final_redirect_url)宝石を使用していました。 – Indyarocks

答えて

51

リダイレクトを追跡するには、このような何か(taken from ruby-doc)を行うことができます

はリダイレクト

require 'net/http' 
require 'uri' 

def fetch(uri_str, limit = 10) 
    # You should choose better exception. 
    raise ArgumentError, 'HTTP redirect too deep' if limit == 0 

    url = URI.parse(uri_str) 
    req = Net::HTTP::Get.new(url.path, { 'User-Agent' => 'Mozilla/5.0 (etc...)' }) 
    response = Net::HTTP.start(url.host, url.port) { |http| http.request(req) } 
    case response 
    when Net::HTTPSuccess  then response 
    when Net::HTTPRedirection then fetch(response['location'], limit - 1) 
    else 
    response.error! 
    end 
end 

print fetch('http://www.ruby-lang.org/') 
+0

ヘッダーにユーザーエージェントを追加する方法についての手掛かりはありますか? レスポンス= Net :: HTTP.get_response(URI.parse(uri_str.encode)、{'User-Agent' => ua}) 私はそれを試みましたが、うまくいかないようです。c:/Ruby191/lib/ruby/1.9.1/net/http.rb:581: 'initialize ':URI :: HTTPをString(TypeError)に変換できません – r3nrut

+0

@ r3nrut:私の編集を参照してください。 – emboss

+1

これは、自分自身にリダイレクトされ、バックスラッシュを追加するリンクでは機能しません。例えば、 'fetch( 'http://epn.dk/okonomi2/dk/ECE5373277/chefoekonom-corydon-skyder-langt-over最初の反復で '#'を生成した後、例外を返します... –

1

後たぶん、あなたはここにhttps://github.com/gdi/curb-fu唯一の事はにいくつかの余分なコードである縁石-fuの宝石を使用することができますリダイレクトに従います。私は以前に以下を使ってきました。それが役に立てば幸い。

require 'rubygems' 
require 'curb-fu' 

module CurbFu 
    class Request 
    module Base 
     def new_meth(url_params, query_params = {}) 
     curb = old_meth url_params, query_params 
     curb.follow_location = true 
     curb 
     end 

     alias :old_meth :build 
     alias :build :new_meth 
    end 
    end 
end 

#this should follow the redirect because we instruct 
#Curb.follow_location = true 
print CurbFu.get('http://<your path>/').body 
+0

Ruby 1.9.1p430を使用してWindowsマシンでcurb-fuを動作させる際に問題が発生しました...私はMacで動作させることができますが、これはWindowsサーバー上で実行する必要があるため、 -fuを実行してインストールを完了します。提案していただきありがとうございます。 – r3nrut

2

私のために働いた参照はここにある: - する必要があります(ここでは受け入れ答えを含む)ほとんどの例と比較するとhttp://shadow-file.blogspot.co.uk/2009/03/handling-http-redirection-in-ruby.html

それだけのドメイン(http://example.comているURLを処理として、それはより堅牢です/)を追加し、具体的にSSLを処理し、相対URLも処理します。

ほとんどの場合、RESTClientのようなライブラリを使用する方がよいでしょうが、低レベルの詳細が必要な場合もあります。

5

ここに示した例に基づいて別のクラスを作成しました。ありがとうございます。私はクッキー、パラメータと例外を追加し、最終的に私は必要なものだ:https://gist.github.com/sekrett/7dd4177d6c87cf8265cd

require 'uri' 
require 'net/http' 
require 'openssl' 

class UrlResolver 
    def self.resolve(uri_str, agent = 'curl/7.43.0', max_attempts = 10, timeout = 10) 
    attempts = 0 
    cookie = nil 

    until attempts >= max_attempts 
     attempts += 1 

     url = URI.parse(uri_str) 
     http = Net::HTTP.new(url.host, url.port) 
     http.open_timeout = timeout 
     http.read_timeout = timeout 
     path = url.path 
     path = '/' if path == '' 
     path += '?' + url.query unless url.query.nil? 

     params = { 'User-Agent' => agent, 'Accept' => '*/*' } 
     params['Cookie'] = cookie unless cookie.nil? 
     request = Net::HTTP::Get.new(path, params) 

     if url.instance_of?(URI::HTTPS) 
     http.use_ssl = true 
     http.verify_mode = OpenSSL::SSL::VERIFY_NONE 
     end 
     response = http.request(request) 

     case response 
     when Net::HTTPSuccess then 
      break 
     when Net::HTTPRedirection then 
      location = response['Location'] 
      cookie = response['Set-Cookie'] 
      new_uri = URI.parse(location) 
      uri_str = if new_uri.relative? 
         url + location 
        else 
         new_uri.to_s 
        end 
     else 
      raise 'Unexpected response: ' + response.inspect 
     end 

    end 
    raise 'Too many http redirects' if attempts == max_attempts 

    uri_str 
    # response.body 
    end 
end 

puts UrlResolver.resolve('http://www.ruby-lang.org') 
+0

このコードスニペットをありがとう!私はあなたがhttp接続( 'finish')を閉じたいかもしれないと思うので、それらは漏れません。とても有難い! – gmcnaughton

+0

これまでのところ私にとって最高の解決策は間違いありません。後で 'html_to_parse = Nokogiri :: HTML(UrlResolver.resolve( 'http://www.ruby-lang.org'))'というページで簡単に作業できます。ありがとう。 – DemitryT

+0

私は100%は分かりませんが、Rubyでは、def関数のスコープから外れると、すべてのオブジェクトが自動的に破棄されると思います。 – sekrett

関連する問題