urllib2 попробуй и кроме 404 - PullRequest
12 голосов
/ 25 ноября 2011

Я пытаюсь просмотреть серию пронумерованных страниц данных, используя urlib2. То, что я хочу сделать, это использовать оператор try, но я мало что знаю об этом. Судя по чтению, кажется, что он основан на определенных «именах», которые являются исключениями, например, IOError и т. Д. Я не знаю, что Я ищу код ошибки, который является частью проблемы.

Я написал / вставил из 'urllib2 недостающее руководство' мою процедуру загрузки страниц urllib2 таким образом:

def fetch_page(url,useragent)
    urlopen = urllib2.urlopen
    Request = urllib2.Request
    cj = cookielib.LWPCookieJar()

    txheaders =  {'User-agent' : useragent}

    if os.path.isfile(COOKIEFILE):
        cj.load(COOKIEFILE)
        print "previous cookie loaded..."
    else:
        print "no ospath to cookfile"

    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
    urllib2.install_opener(opener)
    try:
        req = urllib2.Request(url, useragent)
        # create a request object

        handle = urlopen(req)
        # and open it to return a handle on the url

    except IOError, e:
        print 'Failed to open "%s".' % url
        if hasattr(e, 'code'):
            print 'We failed with error code - %s.' % e.code
        elif hasattr(e, 'reason'):
            print "The error object has the following 'reason' attribute :"
            print e.reason
            print "This usually means the server doesn't exist,",
            print "is down, or we don't have an internet connection."
            return False

    else:
        print
        if cj is None:
            print "We don't have a cookie library available - sorry."
            print "I can't show you any cookies."
        else:
            print 'These are the cookies we have received so far :'
            for index, cookie in enumerate(cj):
                print index, '  :  ', cookie
                cj.save(COOKIEFILE)           # save the cookies again

        page = handle.read()
        return (page)

def fetch_series():

  useragent="Firefox...etc."
  url="www.example.com/01.html"
  try:
    fetch_page(url,useragent)
  except [something]:
    print "failed to get page"
    sys.exit()

Функция bottom - это всего лишь пример, чтобы понять, что я имею в виду. Может кто-нибудь сказать мне, что я должен поместить туда? Я заставил функцию выборки страницы возвращать False, если он получает 404, это правильно? Так почему же кроме False: работа? Спасибо за любую помощь, которую вы можете оказать.

хорошо, согласно совету, я попробовал:

except urlib2.URLError, e:

except URLError, e:

except URLError:

except urllib2.IOError, e:

except IOError, e:

except IOError:

except urllib2.HTTPError, e:

except urllib2.HTTPError:

except HTTPError:

ни один из них не работает.

Ответы [ 3 ]

36 голосов
/ 25 ноября 2011

Вам нужно поймать urllib2.HTTPError, если вы хотите обнаружить 404:

try:
    req = urllib2.Request(url, useragent)
    # create a request object

    handle = urllib2.urlopen(req)
    # and open it to return a handle on the url
except urllib2.HTTPError, e:
    print 'We failed with error code - %s.' % e.code

    if e.code == 404:
        # do stuff..  
    else:
        # other stuff...

    return False
else:
    # ...

Чтобы поймать его в fetch_series ():

def fetch_page(url,useragent)
    urlopen = urllib2.urlopen
    Request = urllib2.Request
    cj = cookielib.LWPCookieJar()
    try:
        urlopen()
        #...
    except IOError, e:
        # ...   
    else:
        #...

def fetch_series(): 
    useragent=”Firefox...etc.”
    url=”www.example.com/01.html
    try:
        fetch_page(url,useragent)
    except urllib2.HTTPError, e:
        print “failed to get page”

http://docs.python.org/library/urllib2.html:

exception urllib2.HTTPError
Будучи исключением (подкласс URLError), HTTPError может также функционировать как неисключительное возвращаемое значение, подобное файлу (то же самое, что urlopen() возвращается).Это полезно при обработке экзотических ошибок HTTP, таких как запросы на аутентификацию.

code
Код состояния HTTP, как определено в RFC 2616. Это числовое значение соответствует значению, найденному в словаре кодовкак найдено в BaseHTTPServer.BaseHTTPRequestHandler.responses.

8 голосов
/ 25 ноября 2011

Рекомендую проверить замечательный модуль requests.

С его помощью вы можете достичь функциональности, о которой вы спрашиваете, примерно так:

import requests
from requests.exceptions import HTTPError

try:
    r = requests.get('http://httpbin.org/status/200')
    r.raise_for_status()
except HTTPError:
    print 'Could not download page'
else:
    print r.url, 'downloaded successfully'

try:
    r = requests.get('http://httpbin.org/status/404')
    r.raise_for_status()
except HTTPError:
    print 'Could not download', r.url
else:
    print r.url, 'downloaded successfully'
2 голосов
/ 12 марта 2016

Интерактивная игра:

Чтобы узнать о характере и возможном содержании таких исключений в python, лучше просто попробуйте использовать клавиши вызова интерактивно:

>>> f = urllib2.urlopen('http://httpbin.org/status/404')
Traceback (most recent call last):
...
  File "C:\Python27\lib\urllib2.py", line 558, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 404: NOT FOUND

Тогда sys.last_value содержит исключениезначение, которое упало до интерактивного - и может быть воспроизведено с:
(используйте TAB +. автоматическое расширение интерактивной оболочки, dir (), vars () ...)

>>> ev = sys.last_value
>>> ev.__class__
<class 'urllib2.HTTPError'>
>>> dir(ev)
['_HTTPError__super_init', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', 'args', 'close', 'code', 'errno', 'filename', 'fileno', 'fp', 'getcode', 'geturl', 'hdrs', 'headers', 'info', 'message', 'msg', 'next', 'read', 'readline', 'readlines', 'reason', 'strerror', 'url']
>>> vars(ev)
{'fp': <addinfourl at 140193880 whose fp = <socket._fileobject object at 0x01062370>>, 'fileno': <bound method _fileobject.fileno of <socket._fileobject object at 0x01062370>>, 'code': 404, 'hdrs': <httplib.HTTPMessage instance at 0x085ADF80>, 'read': <bound method _fileobject.read of <socket._fileobject object at 0x01062370>>, 'readlines': <bound method _fileobject.readlines of <socket._fileobject object at 0x01062370>>, 'next': <bound method _fileobject.next of <socket._fileobject object at 0x01062370>>, 'headers': <httplib.HTTPMessage instance at 0x085ADF80>, '__iter__': <bound method _fileobject.__iter__ of <socket._fileobject object at 0x01062370>>, 'url': 'http://httpbin.org/status/404', 'msg': 'NOT FOUND', 'readline': <bound method _fileobject.readline of <socket._fileobject object at 0x01062370>>}
>>> sys.last_value.code
404

Попробуйте обработать:

>>> try: f = urllib2.urlopen('http://httpbin.org/status/404')
... except urllib2.HTTPError, ev:
...     print ev, "'s error code is", ev.code
...     
HTTP Error 404: NOT FOUND 's error code is 404

Создание простого открывателя, который не генерирует ошибки HTTP:

>>> ho = urllib2.OpenerDirector()
>>> ho.add_handler(urllib2.HTTPHandler())
>>> f = ho.open('http://localhost:8080/cgi/somescript.py'); f
<addinfourl at 138851272 whose fp = <socket._fileobject object at 0x01062370>>
>>> f.code
500
>>> f.read()
'Execution error: <pre style="background-color:#faa">\nNameError: name \'e\' is not defined\n<pre>\n'

Обработчики по умолчанию urllib2.build_opener:

default_classes = [ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler , HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor ]

...