一直以來技術群里會有新入行的同學提問關於urllib和urllib2以及cookielib相關的問題。所以我打算在這里總結一下,避免大家反復回答同樣的問題浪費資源。
這篇屬於教程類的文字,如果你已經非常了解urllib2和cookielib那么請忽略本篇。
首先從一段代碼開始,
#cookie import urllib2 import cookielib cookie = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) request = urllib2.Request(url='http://www.baidu.com/') request.add_header('User-Agent','Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1') response = opener.open(request) for item in cookie: print item.value
很多同學說,我可以直接在openr.open()里寫url,為什么你要用request。其實我這么寫就是為了整理一下一般使用urllib2構造請求的常用步驟。
初步,urllib2構造請求常用步驟(結合上面的代碼):
1、handler
handler既urllib2.build_opener(handler)中傳遞的對象參數,以下是官方的常用handler
urllib2.HTTPHandler() 通過HTTP打開URL
urllib2.CacheFTPHandler() 具有持久FTP連接的FTP處理程序
urllib2.FileHandler() 打開本地文件
urllib2.FTPHandler() 通過FTP打開URL
urllib2.HTTPBasicAuthHandler() 通過HTTP驗證處理
urllib2.HTTPCookieProcessor() 處理HTTP cookie
urllib2.HTTPDefaultErrorHandler() 通過引發HTTPError異常處理HTTP錯誤
urllib2.HTTPDigestAuthHandler() HTTP摘要驗證處理
urllib2.HTTPRedirectHandler() 處理HTTP重定向
urllib2.HTTPSHandler() 通過安全HTTP重定向
urllib2.ProxyHandler() 通過代理重定向請求
urllib2.ProxyBasicAuthHandler 基本的代理驗證
urllib2.ProxyDigestAuthHandler 摘要代理驗證
urllib2.UnknownHandler 處理所有未知URL的處理程序
2、request
request=urllib2.Request(url='')
request.add_data(data) 如果請求是HTTP,則方法改為POST。注意該方法不會將data追加到之前已經設置的任何數據上,而是使用現在的data替換之前的
request.add_header(key,val) key是報頭名,val是包頭值,兩個參數都是字符串
request.add_unredirected_header(key,val) 同上,但是不會添加到重定向請求中
request.set_proxy(host,type) 准備請求到服務器。使用host替換原來的主機,使用type替換原來的請求類型
3、opener
基本的urlopen()函數不支持驗證、cookie或其他的HTTP高級功能。要支持這些功能,必須使用build_opener()函數來創建自己的自定義Opener對象
建自己的自定義Opener對象,通常有兩種方式:
a)
opener=urllib2.OpenerDirector()
opener.add_handler(handler)
b)
opener=urllib2.OpenerDirector()
urllib2.build_opener(handler)
install_opener(opener)
安裝opener作為urlopen()使用的全局URL opener,即意味着以后調用urlopen()時都會使用安裝的opener對象。opener通常是build_opener()創建的opener對象。
4、content_stream
content_stream=opener.open(request)
5、content_stream.read()
通過以上5個步驟,你就可以得到和本篇開始處code差不多的代碼。這樣你就完成了一個urllib2基本使用方式的構造。你也可以將以上5個步驟封裝成類,但是我自己覺得並不是非常簡介。
urllib2模塊不僅可以使用urlopen()函數還可以自定義opener來訪問網頁
但同時要注意:urlretrieve()函數是urllib模塊中的,urllib2模塊中不存在該函數。但是使用urllib2模塊時一般都離不開urllib模塊,因為post的數據需要使用urllib.urlencode()函數來編碼。
進階,urllib2更多使用細節:
1、Proxy的設置
import urllib2 enable_proxy=True proxy_handler=urllib2.ProxyHandler({'http':'http://some-proxy.com:8080'}) null_proxy_handler = urllib2.ProxyHandler({}) if enable_proxy: opener = urllib2.build_opener(proxy_handler) else: opener = urllib2.build_opener(null_proxy_handler) urllib2.install_opener(opener)
ps:使用urllib2.install_opener()會設置urllib2的全局opener。這樣后面的使用會很方便,但不能做更細致的控制,如果想在程序中使用兩個不同的proxy設置等。比較好的方法就是不適用install_opener去更改全局的設置,而只是直接調用opener的open方法代替全局的urlopen方法。
2、timeout設置
# < py2.6 import urllib2 import socket socket.setdefaulttimeoust(10) #one way urllib2.socket.setdefaulttimeout(10)#anther way # >=py2.6 import urllib2 response = urllib2.urlopen('http://www.google.com',timeout=10)
3、在http request中加入特定的header
要加入header,需要使用Request對象:
import urllib2 request = urllib2.Request(url) request.add_header('User-Agent','fake-client') response = urllib2.urlopen(request)
對有些header要特別留意,服務器會針對這些header做檢查:
User-Agent:有些服務器或Proxy會通過該值來判斷是否是瀏覽器發出的請求
Content-Type:在使用REST接口時,服務器會檢查該值,用來確定HTTP Body中的內容該怎樣解析。常見的取值有:
application/xml在XML RPC,如RESTful/SOAP調用時使用
application/json在JSON RPC調用時使用
application/x-www-form-urlencoded瀏覽器提交web表單時使用
4、Redirect
urllib2默認情況下會針對HTTP 3xx返回碼自動進行redirect動作,無需人工配置。要檢測是否發生了redirect動作,只要檢查一下Response的URL和Request的URL是否一直就可以了。
import urllib2 response = urllib2.urlopen('http://www.g.cn') redirected = response.geturl() == 'http://www.google.cn'
如果不想自動redirect,除了使用更地層的httplib庫意外,還可以自定義HTTPRedirectHandler類。
import urllib2 class RedirectHandler(urllib2.HTTPRedirectHandler): def http_error_301(self,req,fp,code,msg,headers): pass def http_error_302(self,req,fp,code,msg,headers): pass opener = urllib2.build_opener(RedirectHandler) opener.open('http://www.google.cn')
5、cookie
urllib2對cookie的處理也是自動的。如果需要得到某個cookie的值,如下
import urllib2 import cookielib cookie = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) response = opener.open('http://www.google.cn') for item in cookie: print item.value
6、使用HTTP的PUT和DELETE方法
urllib2只支持HTTP的GET和POST方法,如果要使用HTTP PUT和DELETE,只能使用比較低層的httplib庫。
import urllib2 request = urllib2.Request(url,data=data) request.get_method=lambda:'PUT'#or 'DELETE' response = urllib2.urlopen(request)
7、得到HTTP的返回碼
對於200OK來說,只要使用urlopen返回的response對象的getcode()方法就可以得到HTTP的返回碼。對其他返回碼來說,urlopen會拋出異常。這時候,就要檢查異常對象的code了
import urllib2 try: response = urllib2.urlopen('http://www.google.cn') except urllib2.HTTPError, e: print e.code
8、debug log
使用urllib2時,可以通過下面的方法把debug log打開,這樣收發包的內容就會在屏幕上打印出了
import urllib2 httpHandler=urllib2.HTTPHandler(debuglevel=1) httpsHandler = urllib2.HTTPSHandler(debuglevel=1) opener = urllib2.build_opener(httpHandler, httpsHandler) urllib2.install_opener(opener) response = urllib2.urlopen('http://www.google.cn')