`open_http’:403 Forbidden(OpenURI :: HTTPError)用于字符串“Steve_Jobs”但不包含任何其他字符串

我正在浏览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以外的任何东西时,它都有效。 这里发生了什么?

我认为这种情况发生在锁定的条目中,如“史蒂夫乔布斯”,“阿尔戈尔”等。这是在您所指的同一本书中指定的:

对于某些页面 – 例如Al Gore的锁定条目 – 如果未指定用户代理,Wikipedia将不会响应Web请求。 “用户代理”通常是指您的浏览器,您可以通过检查您在浏览器中为任何页面请求发送的标头来查看此信息。 通过提供“User-Agent”键值对,(我基本上使用“Ruby”并且似乎工作),我们可以将它作为哈希(我在示例中使用常量HEADERS_HASH)作为第二个参数传递方法调用。

稍后将在http://ruby.bastardsbook.com/chapters/web-crawling/中指定。

当我请求存在维基页面时,您的代码对我来说运行正常(Ruby MRI 1.9.3)。

当我请求一个不存在的wiki页面时,我得到一个mediawiki 404错误代码。

  • Steve_Jobs =>成功
  • Steve_Austin =>成功
  • Steve_Rogers =>成功
  • Steve_Foo =>错误

维基百科做了大量的缓存,所以如果你看到“Steve_Jobs”的答案与其他存在的人不同,那么最好猜测这是因为维基百科正在缓存史蒂夫乔布斯的文章,因为他很有名,并可能添加额外的支票/validation以保护物品免受快速变化,晃动等

解决方案:始终使用用户代理字符串打开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”。

在维基媒体wiki上,如果您没有提供User-Agent标头,或者您提供的是空的或通用标头,则您的请求将因HTTP 403错误而失败。 请参阅我们的用户代理政策。“