1. 程式人生 > >Urllib2 相關總結及異常返回值含義

Urllib2 相關總結及異常返回值含義

介紹

Urllib2是用於獲取URLs(統一資源定位符)的一個Python模組。它以urlopen函式的形式提供了非常簡單的介面。能夠使用各種不同的協議來獲取網址。它還提供一個稍微複雜的介面用於處理常見的情況:如基本身份驗證、cookies、proxies(代理)等。這些是由handlers和openers物件提供。
Urllib2使用相關的網路協議(FTP,http),支援多種獲取URLs的方案(以URL前面的”: ”定義,如:ftp://python.org),這裡主要講最常見的http。
一般情況下,使用urllib2是非常簡單的。當開啟網頁遇到錯誤或異常時,你需要理解HTTP(超文字傳輸協議),最全面最權威HTTP協議可參考RFC2616。本文旨在說明使用urllib2。

獲取URLs

簡單的使用urllib2如下:
    import urllib2
    response = urllib2.urlopen('http://python.org')
    html = response.read()
    print html
可以看到請求的網頁已經被打印出來了。使用urllib2就是如此簡單。
(可使用'ftp:'、'file'代替'http:')
HTTP是基於請求和響應---客戶端發出請求和伺服器端傳送響應。Urllib2 對應Request物件表示你做出HTTP請求,最簡單的形式,建立一個指定要獲取的網址的Request物件。這個Request物件呼叫urlopen,返回URL請求的Response物件。Response物件是一個類似於檔案物件,你可以在Response中使用 .read()。
    import urllib2
    req = urllib2.Request('http://python.org')
    response = urllib2.urlopen(req)
    the_page = response.read()
    print the_page
urlib2可以使用相同Request介面來處理所有URL方案,例如,你可以建立一個FTP請求:
    req = urllib2.Request('ftp://example.com/')
在HTTP協議中,Request物件有兩個額外的事情可以做,第一,你可以通過將資料傳送到伺服器;第二,你可以通過資料的額外的資訊(metadata)或請求到伺服器本身,這個資訊是傳送HTTP'headers'。

Data

有時你想傳送一個數據到URL(通常這個URL指向到CGI(公共閘道器介面)指令碼或其他Web應用程式)。
在HTTP中,經常使用POST請求。這個通常是瀏覽器做的,當你在你填寫的網站上提交HTML表單。
不是所有的POSTs都使用表單的形式:你可以使用POST傳輸任意資料到自己的應用中。在通常的HTML表單中,這些資料需要以標準的形式進行編碼,然後傳遞到Request物件作為data引數。編碼是通過使用urllib庫而不是urllib2庫。
    import urllib
    import urllib2
    url = 'http://www.someserver.com/cgi-bin/register.cgi'
    values = {}
    values['name'] = 'Michael Foord'
    values['location'] = 'Northampton'
    values['language'] = 'Python'

    data = urllib.urlencode(values) #資料進行編碼
    req = urllib2.Request(url,data) #作為data引數傳遞到Request物件中
    response = urllib2.urlopen(req)
    the_page = response.read()
    print the_page
如果你不傳遞data引數,urllib2使用GET請求。GET和POST請求不同的是,POST請求經常有副作用:它們在某種程度上改變系統的狀態。
儘管HTTP標準有明確的說明POSTs總是引起副作用,而GET請求從不會引起副作用,沒有什麼可以防止GET請求沒有副作用,POST請求有副作用。

資料也可以通過在URL本身中HTTP GET請求來編碼。
    >>> import urllib2
    >>> import urllib
    >>> data = {}
    >>> data['name'] = 'Somebody Here'
    >>> data['location'] = 'Northampton'
    >>> data['language'] = 'Python'
    >>> url_values = urllib.urlencode(data)
    >>> print url_values
    name=Somebody+Here&language=Python&location=Northampton
    >>> url = 'http://www.example.com/example.cgi'
    >>> full_url = url + '?' + url_values
    >>> data = urllib2.urlopen(full_url) #這個完整的URL是新增一個?到URL中,其次是編碼的值。

Headers

在這裡討論一個特定的HTTP頭,說明如何新增頭到你的HTTP請求。
一些網站(google)不喜歡由程式來訪問或不同的瀏覽器傳送不同的版本,預設情況下,urllib2標識自己為python urllib / x.y(x.y是Python版本號eg : 2.7),這個可能會混淆網站,或只是簡單的不工作。
瀏覽器標識自己的方式是通過使用者代理(User-Agent)頭。當建立一個Request物件時,你可以通過一個Headers的字典。下面的例子使相同的請求,但將其標識為一個版本的Internet Explorer。
    import urllib
    import urllib2
    url = 'http://www.someserver.com/cgi-bin/register.cgi'
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'

    values = {}
    values['name'] = 'Michael Foord'
    values['location'] = 'Northampton'
    values['language'] = 'Python'

    headers = { 'User-Agent' : user_agent }
    data = urllib.urlencode(values)
    req = urllib2.Request(url,data,headers)
    response = urllib2.urlopen(req)
    the_page = response.read()
    print the_page
response還有兩個常用的方法(info、geturl)。

Handling Exceptions

當urlopen無法處理響應時將引起URLError(儘管像往常一樣使用Python APIs,內建的異常如ValueError、TypeError等也可以引起),在特定的HTTP URLs情況下,HTTPError 是URLError的子類。
URLError
    通常,網路沒有連線或沒有路由到指定的伺服器或指定的伺服器不存在將引起URLError.在這種情形下,異常引發將有個reason屬性,這是一個包含錯誤程式碼和一個文字錯誤資訊的元組。
    import urllib2
    req = urllib2.Request('http://www.pretend_server.org')
    try:
        urllib2.urlopen(req)
    except urllib2.URLError,e:
        print e.reason
    [Errno 11004] getaddrinfo failed    
HTTPError
    每個HTTP響應從伺服器包含一個數字狀態碼”,有時,這個狀態碼錶明伺服器無法滿足請求。預設處理程式將處理一些響應(例如:如果響應是一個“重定向”,則要求客戶端從不同的網址提取文件,urllib2將自行處理);對於那些它不能處理的,urlopen將引起HTTPError。典型的錯誤包括404(沒有找到網頁)、403(禁止請求)、401(需要驗證)。
    HTTPError 例項提出的將一個整型的’code ‘屬性,對應伺服器發出的錯誤Error Codes。因為預設處理程式處理重定向(程式碼在300範圍內),程式碼在100-299表明成功,你通常會看到在400-599範圍錯誤程式碼。
    basehttpserver.basehttprequesthandler.responses是一個有用的字典響應碼,顯示所有的的響應碼由RFC2616的應用。

    # Table mapping response codes to messages; entries have the
    # form {code: (shortmessage, longmessage)}. 
    responses = {
        100: ('Continue', 'Request received, please continue'),
        101: ('Switching Protocols',
        'Switching to new protocol; obey Upgrade header'),

        200: ('OK', 'Request fulfilled, document follows'),
        201: ('Created', 'Document created, URL follows'),
        202: ('Accepted',
        'Request accepted, processing continues off-line'),
        203: ('Non-Authoritative Information', 'Request fulfilled from cache'),
        204: ('No Content', 'Request fulfilled, nothing follows'),
        205: ('Reset Content', 'Clear input form for further input.'),
        206: ('Partial Content', 'Partial content follows.'),

        300: ('Multiple Choices',
        'Object has several resources -- see URI list'),
        301: ('Moved Permanently', 'Object moved permanently -- see URI list'),
        302: ('Found', 'Object moved temporarily -- see URI list'),
        303: ('See Other', 'Object moved -- see Method and URL list'),
        304: ('Not Modified',
        'Document has not changed since given time'),
        305: ('Use Proxy',
        'You must use proxy specified in Location to access this '
        'resource.'),
        307: ('Temporary Redirect',
        'Object moved temporarily -- see URI list'),

        400: ('Bad Request',
        'Bad request syntax or unsupported method'),
        401: ('Unauthorized',
        'No permission -- see authorization schemes'),
        402: ('Payment Required',
        'No payment -- see charging schemes'),
        403: ('Forbidden',
        'Request forbidden -- authorization will not help'),
        404: ('Not Found', 'Nothing matches the given URI'),
        405: ('Method Not Allowed',
        'Specified method is invalid for this server.'),
        406: ('Not Acceptable', 'URI not available in preferred format.'),
        407: ('Proxy Authentication Required', 'You must authenticate with '
        'this proxy before proceeding.'),
        408: ('Request Timeout', 'Request timed out; try again later.'),
        409: ('Conflict', 'Request conflict.'),
        410: ('Gone',
        'URI no longer exists and has been permanently removed.'),
        411: ('Length Required', 'Client must specify Content-Length.'),
        412: ('Precondition Failed', 'Precondition in headers is false.'),
        413: ('Request Entity Too Large', 'Entity is too large.'),
        414: ('Request-URI Too Long', 'URI is too long.'),
        415: ('Unsupported Media Type', 'Entity body in unsupported format.'),
        416: ('Requested Range Not Satisfiable',
        'Cannot satisfy request range.'),
        417: ('Expectation Failed',
        'Expect condition could not be satisfied.'),

        500: ('Internal Server Error', 'Server got itself in trouble'),
        501: ('Not Implemented',
        'Server does not support this operation'),
        502: ('Bad Gateway', 'Invalid responses from another server/proxy.'),
        503: ('Service Unavailable',
        'The server cannot process the request due to a high load'),
        504: ('Gateway Timeout',
        'The gateway server did not receive a timely response'),
        505: ('HTTP Version Not Supported', 'Cannot fulfill request.'),
    }

伺服器響應引起的錯誤通過返回一個HTTP錯誤程式碼和錯誤頁面,可以使用HTTPError例項為頁面上的響應中返回。這個也有code屬性,也有read、geturl、info方法。
    import urllib2

    req = urllib2.Request('http://www.python.org/fish.html')
    try:
        urllib2.urlopen(req)
    except urllib2.URLError,e:
        print e.code
        print e.read()
        print e.geturl()
        print e.info()

Wrapping it up(包裝)
如果你想編寫HTTPError或URLError有兩個基本方法。(更喜歡第二種方法)
Number1
同時處理HTTPError和URLError,應該把HTTPError放在URLError前面。由於HTTPError是URLError的子類,否則URLError也會捕獲一個HTTPError錯誤。
    from urllib2 import Request,urlopen,URLError,HTTPError

    req = Request('http://www.python.org/fish.html')
    try:
        response = urlopen(req)
    except HTTPError,e:
        print 'The server couldn\'t fulfill the request'
        print 'Error code:',e.code
    except URLError,e:
        print 'We failed to reache a server.'
        print 'Reason:',e.reason
    else:
        #everything is fine
        response.getcode()
Number 2
由於HTTPError是URLError的子類,可以避免匯入HTTPError.改進如下:
    from urllib2 import Request,urlopen,URLError

    req = Request('http://www.python.org/fish.html')
    try:
        response = urlopen(req)
    except URLError,e:
        if hasattr(e,'reason'):
            print 'We failed to reach a server.'
            print 'Reason:',e.reason
        elif hasattr(e,'code'):
            print 'The server couldn\'t fulfill the request'
            print 'Error code:',e.code
        else:
            #everything is fine
            response.getcode()
注意,URLError是內建異常IOError的子類,同樣也可避免匯入URLError.在某些情況下,urllib2也可能會引起scoker.error。

    from urllib2 import Request,urlopen

    req = Request('http://www.python.org/fish.html')
    try:
        response = urlopen(req)
    except IOError,e:
        if hasattr(e,'reason'):
            print 'We failed to reach a server.'
            print 'Reason:',e.reason
        elif hasattr(e,'code'):
            print 'The server couldn\'t fulfill the request'
            print 'Error code:',e.code
    else:
        #everything is fine
        response.getcode()

BadStatusLine and HttpException 
    由一兩種情況例外,不繼承IOError引起的異常,一種是由httplib模組定義的BadStatusLine異常,當請求的頁頁面是空白時會引起這個異常。它沒有繼承IOError,而是從HttpException繼承(在httplib中重新定義,直接從Exception中繼承),可能還有其他的情況下,這些例外可以滲入到使用者urllib2。你可以將這些異常型別,從httplib中直接抓取,或者用一個"catch-all"異常語句來處理任何發生的錯誤。

info and geturl

以urlopen返回的響應(或HTTPError例項)有兩個有用的資訊info和方法geturl。
geturl --- 返回抓取頁面的真正的URL。這是非常有用的,因為urlopen可能跟著一個重定向。獲取的頁面的網址可能與請求的地址不相同。
info --- 返回一個描述頁面抓取的字典物件,特別是伺服器傳送的標頭檔案。這是當前的一個httplib.httpmessage例項。典型的heade包括'Content-length', 'Content-type'等。

Openers and Handlers

當使用opener(也許是urllib2.openerdirector的命名例項)獲取一個網頁時,通常我們通過urlopen已經使用預設的opener, 但是我們可以建立自定義openers。openers使用處理程式。所有的“重起”是由處理程式完成的。每個處理程式知道如何為一個特定的URL方案(HTTP,FTP等)開啟網址,或如何處理網址開啟的一個方面,例如,HTTP重定向或者HTTP cookies。

如果你想獲取安裝了特定處理程式的網址,需要建立openers。例如,獲得opener處理cookies,或者獲得opener不處理重定向。

建立一個opener,例項化一個openerdirector,然後反覆呼叫.add_handle(some_handler_instance)。或者,你可以使用build_opener,這是一個方便的功能,用於建立具有一個單一的函式呼叫opener物件,.build_opener預設情況下增加了幾個程式。但提供了一個快速的方法來新增更多或重寫預設的處理程式。

其他型別的處理程式,你可能希望可以處理proxies(代理)、authenticarion(身份驗證)和其他常見情況。

install_opener預設情況下可以開啟一個opener物件(全域性),這意味著呼叫urlopen將使用已安裝的opener物件。Opener物件有一個open方法,使用urlopen函式直接抓取urls,不需要呼叫install_opener,除非為了方便。

Basic Authentication

說明如何建立和安裝處理程式,我們將使用httpbasicauthhandler。對於這個問題的更詳細的討論,包括對基本認證如何工作的解釋,看看 Basic Authentication Tutorial.
當需要身份驗證時,伺服器傳送一個頭(以及401個錯誤程式碼)請求身份驗證。

這指定的身份驗證scheme(方案)和'realm'(“領域”)。header是這樣的:WWW-Authenticate:SCHEME realm=“REALM”。

e.g.
    Www-authenticate: Basic realm="cPanel Users"
然後,客戶端應以適當的名稱和密碼重試請求,以在請求中包含作為header的域中的適當name和password。這是“基本的身份驗證”為了簡化這一過程,我們可以建立一個httpbasicauthhandler例項和opener使用此處理程式。

httpbasicauthhandler使用物件稱為一個密碼管理器,來處理URL和伺服器密碼使用者名稱對映,如果你知道這個領域是什麼(從伺服器傳送的身份驗證頭),你可以使用HTTPPasswordMgr。通常不關心的領域是什麼。
在這種情況下,它使用很方便httppasswordmgrwithdefaultrealm。
這允許您指定一個預設的使用者名稱和密碼的網址。

我們表明這個提供None作為 add_password方法的域引數。頂級的網址是第一個需要認證的網址。網址“deeper”和URL傳遞給.add_password()也將匹配。

    # create a password manager
    password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()

    # Add the username and password.
    # If we knew the realm, we could use it instead of ``None``.
    top_level_url = "http://example.com/foo/"
    password_mgr.add_password(None,top_level_url,username,password)
    handler = urllib2.HTTPBasicAuthHandler(password_mgr)
    # create "opener" (OpenerDirector instance)
    opener = urllib2.build_opener(handler)
    # use the opener to fetch a URL
    opener.open(a_url)
    # Install the opener.
    # Now all calls to urllib2.urlopen use our opener.
    urllib2.install_opener(opener)
注意:
在上面的例子中,我們只提供給我們的httpbasicauthhandler build_opener。預設情況下,openers有正常情況下的處理程式--ProxyHandler,UnknownHandler,HTTPHandler, HTTPDefaultErrorHandler,HTTPRedirectHandler,FTPHandler,FileHandler,HTTPErrorProcessor.

top_level_url實際上是一個完整的URL(包括“http”計劃的組成部分和主機名和可選的埠號)e.g. "http://example.com/" 或者 一個"authority"(i.e.主機名,包括主機名)e.g. "example.com" or "example.com:8080"(後者的例子包括一個埠號)這個 authority
如果存在,一定不能包含“userinfo”部分--例如:[email protected]:example.com不正確

proxies

urllib2自動檢測代理伺服器設定和使用.這是通過proxyhandler是正常的處理程式鏈的一部分.通常情況下,這是一件好事,但也有一些時候,它可能不會有幫助。一個辦法是建立我們自己的proxyhandler,沒有代理的定義。這是使用類似的步驟來設定一個基本的身份驗證處理程式:
    proxy_support = urllib2.ProxyHandler({})
    opener = urllib2.build_opener(proxy_support)
    urllib2.install_open(opener)
注意:
    當前的urllib2不支援通過proxy抓取https,這個可能是個問題.

Sockets and Layers

Python從網路獲取資源支援分層,urllib2使用httplib的庫,從而使用Socket庫。在Python2.3你可以指定多少socket,應該等待超時前的反應。這可能是有用的應用程式,必須獲取網頁。預設情況下,socket模組沒有超時和可以掛起。
目前,socket超時不暴露httplib或者urllib2。然而,你可以在全域性範圍內為所有的socket設定預設超時使用。
    import socket
    import urllib2
    # timeout in seconds
    timeout = 10
    socket.setdefault timeout(timeout)
    #this call to urllib2.urlopen now uses the default timeout
    # we have set in the socket module
    req = urllib2.Request('http://www.voidspace.org.uk')
    response = urllib2.urlopen(req)

參考網址:https://www.cnblogs.com/billyzh/p/5819957.html

相關推薦

Urllib2 相關總結異常返回含義

介紹Urllib2是用於獲取URLs(統一資源定位符)的一個Python模組。它以urlopen函式的形式提供了非常簡單的介面。能夠使用各種不同的協議來獲取網址。它還提供一個稍微複雜的介面用於處理常見的情況:如基本身份驗證、cookies、proxies(代理)等。這些是由h

循環控制狀態返回的應用實踐(分析apache日誌)

循環語句 ns3 總結 字段 順序 awk 字節數 shell 訪問日誌 12.1 break,continue,exit,return的區別和對比break和continue在條件語句以及循環語句(for,while,if等)中用於控制程序的走向;exit用戶終止所有語句

循環控制狀態返回

cti 次循環 then echo init.d 代碼 gre return random 1.break、continue、exit、return的區別 break、continue在條件語句及循環語句(for、while、if等)中用於控制程序的走向;而exit則用於終

http返回含義

  1xx:資訊響應類,表示接收到請求並且繼續處理2xx:處理成功響應類,表示動作被成功接收、理解和接受 3xx:重定向響應類,為了完成指定的動作,必須接受進一步處理4xx:客戶端錯誤,客戶請求包含語法錯誤或者是不能正確執行5xx:

解讀Java中BigDecimal.ZERO.compareTo()的返回含義

Java compareTo() 用法 例如: public static void main(String[] args) {     BigDecimal bnum1, bnum2;     bnum1 = new BigDecimal("10");     bnu

2018花旗金融產品技術支援和開發面試相關總結個人感受

       網上有關花旗相關面試的博文不多,特此總結了技術支援和開發的面試一些問題(本人是技術支援,開發的面試問題是另一位小姐姐提供的),問題難度差不多,技術支援對英語要求更高些(終面全程英語面試),供後續校招的同學們參考。        花旗金融可以發簡歷到[email

ajax同步異步設置導致的問題return返回返回ajax請求的數據)

() log inf 應該 頁面數據 spa mha soft add 一、ajax同步異步設置導致父子頁面數據更新不一致問題。   1、在修復入宿退宿功能時,發現點擊退宿、入宿按鈕時。父頁面數據更新了但是子頁面數據要重新打開才能更新。如下圖:          因為

C++11:decltype型別推導追蹤返回型別

C++11:decltype型別推導及追蹤返回值型別 使用decltype進行自動型別推導 先看一段cppreference上面的解釋:decltype 指定符 可以看下面的一段程式碼: #include <bits/stdc++.h> using na

用sp_executesql執行動態SQL語句獲得返回

過去我執行拼湊出來的動態SQL語句,都直接使用EXEC @sql 的方式。有好幾次,都看到有資料說,應該儘量使用 sp_executesql。究其原因,是因為僅僅引數不同的情況下,sp_executesql可以重用執行計劃,這不就有跟儲存過程一樣的優勢了嗎?同時,sp_exe

獲取瀏覽器語言的完美方案。(各瀏覽器對 navigator 物件中幾個與語言相關的屬性的返回存在差異)

標準參考 無 問題描述 各瀏覽器對 navigator 物件中幾個與語言相關的屬性(language、userLanguage、browserLanguage、 systemLanguage)的返回值存在很大的差異。 造成的影響 由於不同瀏覽器對這幾個屬性的返回值有很

各瀏覽器對 navigator 物件中幾個與語言相關的屬性的返回存在差異

轉載自:http://www.w3help.org/zh-cn/causes/BX2040 標準參考 無 問題描述 各瀏覽器對 navigator 物件中幾個與語言相關的屬性(language、userLanguage、browserLanguage、 syste

bash中if條件語句的使用bash返回的注意事項

#!/bin/bash #bash函式以及返回值的注意事項 function showgrade(){     if [ ! -z "$1" ];then         echo "Your gra

http協議中各個響應狀態200_301_404_500等返回含義快速一覽

一、定義從HTTP的定義可以看出,HTTP協議是網際網路上進行資料通訊的基礎協議,用來交換或傳輸超文字。超文字是一種結構化的文字,在包含文字的節點之間使用邏輯連結(也叫超連結)。二、概述HTTP是基於TCP/IP協議的應用層協議。HTTP允許進行客戶端和伺服器之間的通訊。通過HTTP或HTTPS請求的資源由U

NTSTATUS型別返回含義

0,   "STATUS_WAIT_0" 1,   "STATUS_WAIT_1" 2,   "STATUS_WAIT_2" 3,   "STATUS_WAIT_3" 63,   "STATUS_WAIT_63" 128,   "STATUS_ABANDONED_WAIT_

轉:NTSTATUS型別返回含義

0,   "STATUS_WAIT_0" 1,   "STATUS_WAIT_1" 2,   "STATUS_WAIT_2" 3,   "STATUS_WAIT_3" 63,   "STATUS_WAIT_63" 128,   "STATUS_ABANDONED_WAIT_

springboot統一restful返回統一異常處理

creat hand origin 錯誤信息 ogr let 執行 per 所有 統一返回restful數據: 首先確定需要返回的json數據的格式,定義一個統一返回類 package com.unicom.microservice.peixun.peixun_matb3.

set容器的insert返回總結

div 操作 using com .com air blog article () #include <iostream> #include <set> #include <string> using namespace std;

怎樣獲取shell函數的返回shell命令的返回

返回 echo tro bin 狀態 pre code shell函數 sta 1、獲取shell函數調用的返回值: #!/bin/sh info() { cat jlb.sh } res=`info` echo &quo

JDBC和異常總結常見使用

javaJDBC-一、JDBC連接過程01.註冊驅動Class.forName("oracle.jdbc.driver.OracleDriver");02.獲取連接Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@10.0.19.

execute、executeUpdate、executeQuery三者的區別(返回

更新 必須 定義 查詢語句 else 類型 表示 例如 單個 1. ResultSet executeQuery(String sql); 執行SQL查詢,並返回ResultSet 對象。 2.int executeUpdate(String s