9

http://ruby.bastardsbook.com/で提供されている Ruby チュートリアルを行っていたところ、次のコードに遭遇しました。

require "open-uri"

remote_base_url = "http://en.wikipedia.org/wiki"
r1 = "Steve_Wozniak"
r2 = "Steve_Jobs"
f1 = "my_copy_of-" + r1 + ".html"
f2 = "my_copy_of-" + r2 + ".html"

# read the first url
remote_full_url = remote_base_url + "/" + r1
rpage = open(remote_full_url).read

# write the first file to disk
file = open(f1, "w")
file.write(rpage)
file.close

# read the first url
remote_full_url = remote_base_url + "/" + r2
rpage = open(remote_full_url).read

# write the second file to disk
file = open(f2, "w")
file.write(rpage)
file.close

# open a new file:
compiled_file = open("apple-guys.html", "w")

# reopen the first and second files again
k1 = open(f1, "r")
k2 = open(f2, "r")

compiled_file.write(k1.read)
compiled_file.write(k2.read)

k1.close
k2.close
compiled_file.close

コードは次のトレースで失敗します。

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:277:in `open_http': 403 Forbidden (OpenURI::HTTPError)
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open'
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop'
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:162:in `catch'
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop'
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri'
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:518:in `open'
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:30:in `open'
    from /Users/arkidmitra/tweetfetch/samecode.rb:11

私の問題は、コードが失敗することではなく、r2 を Steve_Jobs 以外に変更すると、コードが機能することです。ここで何が起きてるの?

4

2 に答える 2

10

存在する wiki ページをリクエストすると、あなたのコードは問題なく動作します (Ruby MRI 1.9.3)。

存在しないウィキ ページをリクエストすると、mediawiki 404 エラー コードが表示されます。

  • Steve_Jobs => 成功
  • Steve_Austin => 成功
  • Steve_Rogers => 成功
  • Steve_Foo => エラー

ウィキペディアは大量のキャッシングを行っているため、「 Steve_Jobs」に対する応答が実際に存在する他の人々とは異なる場合、これはウィキペディアが有名なスティーブ ジョブズの記事をキャッシュしており、余分なチェックを追加している可能性があるためだと推測できます。急速な変更、改ざんなどから記事を保護するための検証。

あなたのための解決策:常にユーザーエージェント文字列でURLを開きます。

rpage = open(remote_full_url, "User-Agent" => "Whatever you want here").read

Mediawiki ドキュメントの詳細: 「MediaWiki Web サービス API に対して HTTP 要求を行うときは、クライアントを適切に識別する User-Agent ヘッダーを必ず指定してください。クライアント ライブラリによって提供されるデフォルトの User-Agent を使用しないでください。クライアントの名前とバージョン番号を含むカスタム ヘッダーを作成します。「MyCuteBot/0.1」のようなものです。

ウィキメディア ウィキでは、User-Agent ヘッダーを提供しない場合、または空または一般的なヘッダーを提供する場合、リクエストは HTTP 403 エラーで失敗します。ユーザー エージェント ポリシーを参照してください。」

于 2012-06-10T00:56:03.630 に答える
2

これは、「Steve Jobs」、「Al-Gore」などのロックダウンされたエントリで発生すると思います。これは、参照している同じ本で指定されています。

Al Goreのロックダウンされたエントリなど、一部のページでは、User-Agentが指定されていない場合、WikipediaはWeb要求に応答しません。「ユーザーエージェント」は通常、ブラウザを指します。これは、ブラウザでページリクエストに対して送信するヘッダーを調べることで確認できます。「User-Agent」キーと値のペアを提供することで(基本的に「Ruby」を使用し、機能しているようです)、ハッシュ(例では定数HEADERS_HASHを使用)として2番目の引数として渡すことができます。メソッド呼び出し。

後でhttp://ruby.bastardsbook.com/chapters/web-crawling/で指定されます

于 2012-06-18T17:49:31.397 に答える