

Rubyのopen-uriを用いて、[Internet
archive](https://web.archive.org/)のhttps://web.archive.org/web/20150421015448/<http://www.google.com>/とhttps://web.archive.org/web/20150408183138/<https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830>/にアクセスしているのですが、googleのアーカイブには正しくアクセスできるものの、もう一つのURLは"400
Bad Request"が返っています。  
また、アクセスするURLによっては、成功したり失敗したりすることもあります。

下記のサイトでは、"400 Bad Requestは殆どの場合ユーザー側に問題がある。"とありましたので対策を考えているのですが、open-
uriを使用する際にTIPSがありますでしょうか。  
情報ありましたら、教えていただけると助かります。

400 Bad Request  
<http://www.bmoo.net/archives/2012/02/312554.html>

なお使用しているRubyは、2.2になります。  
ruby 2.2.0preview1 (2014-09-17 trunk 47616) [x86_64-darwin14]  
=====/ソースコード

[code]

    require 'open-uri'
    
    def rescue_open(url)
      rescue_num = 0
      begin
        res = open(url)
      rescue => e
        print "error raise in rescue: "
        p e
        print "url = #{url}\n"
        if rescue_num < 5 then
          sleep 1
          rescue_num = rescue_num + 1
          retry
        else
          res = nil
        end
      end
      puts "open OK url = #{url}\n\n" unless res == nil
      res
    end
    
    f = rescue_open('https://web.archive.org/web/20150421015448/http://www.google.com/')
    
    f = rescue_open('https://web.archive.org/web/20150408183138/https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830/')
    
[/code]

========/実行結果  
open OK url =
<https://web.archive.org/web/20150421015448/http://www.google.com/>

error raise in rescue: #  
url =
<https://web.archive.org/web/20150408183138/https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830/>  
error raise in rescue: #  
url =
<https://web.archive.org/web/20150408183138/https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830/>  
error raise in rescue: #  
url =
<https://web.archive.org/web/20150408183138/https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830/>  
error raise in rescue: #  
url =
<https://web.archive.org/web/20150408183138/https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830/>  
error raise in rescue: #  
url =
<https://web.archive.org/web/20150408183138/https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830/>  
error raise in rescue: #  
url =
<https://web.archive.org/web/20150408183138/https://suumo.jp/tochi/tokyo/sc_nishitokyo/nc_84783830/>


CC BY-SA 3.0
2015-04-21T11:27:26.027
9385
2015-04-21T18:32:03.233
4260
question
ruby
Rubyのopen-uriの400 Bad Request対策について(Internet archive(archive.org)へのアクセスについて)


上記urlにFirefoxでアクセスするとurlが書き換わるので、多分3xxの応答にopen-uriが対応していないように思われます。  
open処理を[ここ](http://docs.ruby-
lang.org/ja/2.2.0/library/net=2fhttp.html)を参考にNet::HTTPで書き換えると、上記urlでもうまく動作するようになりました。  
また、クロールするならMechanizeを使ったほうが色々楽だと思います。（[参考](http://www.xmisao.com/2013/10/05/ruby-
www-mechanize.html)）

余談ですが、Ruby 2.2系列は2.2.2が出ていますので、特に理由がなければ最新のものに更新したほうがいいと思います。


CC BY-SA 3.0
2015-04-21T14:32:56.337
9402
2015-04-21T14:32:56.337
7900
9385
answer


気になったので open-uri.rb を読んでみました。(2.2.0に付属のものですが、2.2.0preview1でも同じはずです。)

次の流れで Bad request になっているようです。

  1. open-uri は内部でリダイレクト処理を行う
  2. リダイレクト時、web.archive.org は規格 (HTTP/1.1) に反してLocationに相対URLを入れて返してくる
  3. そのような不正なレスポンスでも、open-uriは頑張って絶対URLに変換しようとする
  4. 絶対URLに変換する際、連続した `/` が1個の `/` に変換されてしまう。(Rubyにおける "uri" の仕様; URLとしても連続した `/` は本来正しくない…はず。)
[code]     例:

    URI("http://example.jp/") + URI("/foo//bar")
    => #<URI::HTTP:0x007f94dc0b5c70 URL:http://example.jp/foo/bar>
    
[/code]

  5. 結果的に web.archive.org が想定しているものと異なったURL (途中の `https://suumo.jp` が `https:/suumo.jp` になっている) をリクエストしてしまう。

  6. web.archive.org が Bad Request を返す。

本来は open-uri の実装で問題無く利用できるはずですが、規格に適合しないサーバ (現実にはよくある) を利用する場合は net/http
など別のライブラリを利用するのが良さそうです。

※open-uri は認証+リダイレクト周りでもちょっとクセがあったりするので、注意が必要です。(参考:
<https://stackoverflow.com/questions/13763399/openuri-
causing-401-unauthorized-error-with-https-url/13765887#13765887>)


CC BY-SA 3.0
2015-04-21T18:32:03.233
9412
2015-04-21T18:32:03.233
2017-05-23T12:38:56.467
-1
76
9385
answer