web-dev-qa-db-ja.com

urllib.urlretrieveで404エラーをキャッチする方法

背景:フック関数がサポートされているため、urllib.urlretrieveモジュールの他の関数とは対照的に、 urllib* を使用しています(以下のreporthookを参照)。 。これは、テキストのプログレスバーを表示するために使用されます。これはPython> = 2.6です。

>>> urllib.urlretrieve(url[, filename[, reporthook[, data]]])

ただし、urlretrieveは非常に馬鹿げているため、HTTPリクエストのステータスを検出する方法がありません(例:404または200でしたか?)。

>>> fn, h = urllib.urlretrieve('http://google.com/foo/bar')
>>> h.items() 
[('date', 'Thu, 20 Aug 2009 20:07:40 GMT'),
 ('expires', '-1'),
 ('content-type', 'text/html; charset=ISO-8859-1'),
 ('server', 'gws'),
 ('cache-control', 'private, max-age=0')]
>>> h.status
''
>>>

フックのようなサポート(プログレスバーを表示するため)と適切なHTTPエラー処理を備えたリモートHTTPファイルをダウンロードするための最もよく知られている方法は何ですか?

27

urllib.urlretrieveの完全なコードを確認してください:

def urlretrieve(url, filename=None, reporthook=None, data=None):
  global _urlopener
  if not _urlopener:
    _urlopener = FancyURLopener()
  return _urlopener.retrieve(url, filename, reporthook, data)

つまり、 rllib.FancyURLopener (パブリックurllib APIの一部)を使用できます。 http_error_defaultをオーバーライドして、404を検出できます。

class MyURLopener(urllib.FancyURLopener):
  def http_error_default(self, url, fp, errcode, errmsg, headers):
    # handle errors the way you'd like to

fn, h = MyURLopener().retrieve(url, reporthook=my_report_hook)
28
orip

次を使用する必要があります。

import urllib2

try:
    resp = urllib2.urlopen("http://www.google.com/this-gives-a-404/")
except urllib2.URLError, e:
    if not hasattr(e, "code"):
        raise
    resp = e

print "Gave", resp.code, resp.msg
print "=" * 80
print resp.read(80)

編集:ここでの理論的根拠は、例外的な状態を予期しない限り、それが発生することは例外であり、おそらくそれについて考えさえしなかったということです-したがって、コードを続行させる代わりに失敗したときに実行すると、デフォルトの動作は(かなり賢明に)実行を禁止します。

14
lericson

URL Openerオブジェクトの「retreive」メソッドはreporthookをサポートし、404で例外をスローします。

http://docs.python.org/library/urllib.html#url-opener-objects

2
Mark