鍍金池/ 教程/ Python/ 標(biāo)準(zhǔn)庫(kù) (6)
標(biāo)準(zhǔn)庫(kù) (4)
如何成為 Python 高手
標(biāo)準(zhǔn)庫(kù) (6)
標(biāo)準(zhǔn)庫(kù) (3)
類(2)
Pandas 使用 (2)
xml
用 tornado 做網(wǎng)站 (5)
文件(1)
練習(xí)
列表(3)
從小工到專家
除法
錯(cuò)誤和異常 (2)
函數(shù)(1)
用 tornado 做網(wǎng)站 (7)
為做網(wǎng)站而準(zhǔn)備
函數(shù)練習(xí)
標(biāo)準(zhǔn)庫(kù) (8)
Pandas 使用 (1)
回顧 list 和 str
字典(1)
用 tornado 做網(wǎng)站 (3)
字符串(1)
函數(shù)(2)
寫一個(gè)簡(jiǎn)單的程序
將數(shù)據(jù)存入文件
語句(5)
SQLite 數(shù)據(jù)庫(kù)
集成開發(fā)環(huán)境(IDE)
集合(1)
類(1)
用 tornado 做網(wǎng)站 (6)
用 tornado 做網(wǎng)站 (2)
自省
語句(4)
錯(cuò)誤和異常 (1)
用 tornado 做網(wǎng)站 (4)
集合(2)
列表(1)
標(biāo)準(zhǔn)庫(kù) (1)
生成器
mysql 數(shù)據(jù)庫(kù) (1)
第三方庫(kù)
實(shí)戰(zhàn)
運(yùn)算符
類(3)
字典(2)
語句(1)
數(shù)和四則運(yùn)算
語句(2)
文件(2)
MySQL 數(shù)據(jù)庫(kù) (2)
電子表格
迭代器
mongodb 數(shù)據(jù)庫(kù) (1)
特殊方法 (2)
特殊方法 (1)
字符編碼
編寫模塊
用 tornado 做網(wǎng)站 (1)
標(biāo)準(zhǔn)庫(kù) (5)
函數(shù)(4)
類(5)
字符串(2)
關(guān)于 Python 的故事
函數(shù)(3)
字符串(4)
處理股票數(shù)據(jù)
常用數(shù)學(xué)函數(shù)和運(yùn)算優(yōu)先級(jí)
字符串(3)
為計(jì)算做準(zhǔn)備
多態(tài)和封裝
類(4)
迭代
語句(3)
錯(cuò)誤和異常 (3)
分析 Hello
Python 安裝
標(biāo)準(zhǔn)庫(kù) (2)
列表(2)
元組

標(biāo)準(zhǔn)庫(kù) (6)

urllib

urllib 模塊用于讀取來自網(wǎng)上(服務(wù)器上)的數(shù)據(jù),比如不少人用 Python 做爬蟲程序,就可以使用這個(gè)模塊。先看一個(gè)簡(jiǎn)單例子:

>>> import urllib
>>> itdiffer =  urllib.urlopen("http://www.itdiffer.com")

這樣就已經(jīng)把我的網(wǎng)站www.itdiffer.com首頁的內(nèi)容拿過來了,得到了一個(gè)類似文件的對(duì)象。接下來的操作跟操作一個(gè)文件一樣(如果忘記了文件怎么操作,可以參考:《文件(1)

>>> print itdiffer.read()
<!DOCTYPE HTML>
<html>
    <head>
        <title>I am Qiwsir</title>
....//因?yàn)閮?nèi)容太多,下面就省略了

就這么簡(jiǎn)單,完成了對(duì)一個(gè)網(wǎng)頁的抓取。當(dāng)然,如果你真的要做爬蟲程序,還不是僅僅如此。這里不介紹爬蟲程序如何編寫,僅說明 urllib 模塊的常用屬性和方法。

>>> dir(urllib)
['ContentTooShortError', 'FancyURLopener', 'MAXFTPCACHE', 'URLopener', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__version__', '_asciire', '_ftperrors', '_have_ssl', '_hexdig', '_hextochr', '_hostprog', '_is_unicode', '_localhost', '_noheaders', '_nportprog', '_passwdprog', '_portprog', '_queryprog', '_safe_map', '_safe_quoters', '_tagprog', '_thishost', '_typeprog', '_urlopener', '_userprog', '_valueprog', 'addbase', 'addclosehook', 'addinfo', 'addinfourl', 'always_safe', 'base64', 'basejoin', 'c', 'ftpcache', 'ftperrors', 'ftpwrapper', 'getproxies', 'getproxies_environment', 'i', 'localhost', 'noheaders', 'os', 'pathname2url', 'proxy_bypass', 'proxy_bypass_environment', 'quote', 'quote_plus', 're', 'reporthook', 'socket', 'splitattr', 'splithost', 'splitnport', 'splitpasswd', 'splitport', 'splitquery', 'splittag', 'splittype', 'splituser', 'splitvalue', 'ssl', 'string', 'sys', 'test1', 'thishost', 'time', 'toBytes', 'unquote', 'unquote_plus', 'unwrap', 'url2pathname', 'urlcleanup', 'urlencode', 'urlopen', 'urlretrieve']

選幾個(gè)常用的介紹,其它的如果讀者用到,可以通過查看文檔了解。

urlopen()

urlopen() 主要用于打開 url 文件,然后就獲得指定 url 的數(shù)據(jù),接下來就如同在本地操作文件那樣來操作。

Help on function urlopen in module urllib:

urlopen(url, data=None, proxies=None) Create a file-like object for the specified URL to read from.

得到的對(duì)象被叫做類文件。從名字中也可以理解后面的操作了。先對(duì)參數(shù)說明一下:

  • url:遠(yuǎn)程數(shù)據(jù)的路徑,常常是網(wǎng)址
  • data:如果使用 post 方式,這里就是所提交的數(shù)據(jù)
  • proxies:設(shè)置代理

關(guān)于參數(shù)的詳細(xì)說明,還可以參考Python的官方文檔,這里僅演示最常用的,如前面的例子那樣。

當(dāng)?shù)玫搅祟愇募?duì)象之后,就可以對(duì)它進(jìn)行操作。變量 itdiffer 引用了得到的類文件對(duì)象,通過它查看:

>>> dir(itdiffer)
['__doc__', '__init__', '__iter__', '__module__', '__repr__', 'close', 'code', 'fileno', 'fp', 'getcode', 'geturl', 'headers', 'info', 'next', 'read', 'readline', 'readlines', 'url']

讀者從這個(gè)結(jié)果中也可以看出,這個(gè)類文件對(duì)象也是可迭代的。常用的方法:

  • read(),readline(),readlines(),fileno(),close():都與文件操作一樣,這里不再贅述。可以參考前面有關(guān)文件章節(jié)
  • info():返回頭信息
  • getcode():返回 http 狀態(tài)碼
  • geturl():返回 url

簡(jiǎn)單舉例:

>>> itdiffer.info()
<httplib.HTTPMessage instance at 0xb6eb3f6c>
>>> itdiffer.getcode()
200
>>> itdiffer.geturl()
'http://www.itdiffer.com'

更多情況下,已經(jīng)建立了類文件對(duì)象,通過對(duì)文件操作方法,獲得想要的數(shù)據(jù)。

對(duì) url 編碼、解碼

url 對(duì)其中的字符有嚴(yán)格要求,不許可某些特殊字符,這就要對(duì) url 進(jìn)行編碼和解碼了。這個(gè)在進(jìn)行 web 開發(fā)的時(shí)候特別要注意。urllib 模塊提供這種功能。

  • quote(string[, safe]):對(duì)字符串進(jìn)行編碼。參數(shù) safe 指定了不需要編碼的字符
  • urllib.unquote(string) :對(duì)字符串進(jìn)行解碼
  • quote_plus(string [ , safe ] ) :與 urllib.quote 類似,但這個(gè)方法用'+'來替換空格' ',而 quote 用'%20'來代替空格
  • unquote_plus(string ) :對(duì)字符串進(jìn)行解碼;
  • urllib.urlencode(query[, doseq]):將 dict 或者包含兩個(gè)元素的元組列表轉(zhuǎn)換成 url 參數(shù)。例如{'name': 'laoqi', 'age': 40}將被轉(zhuǎn)換為"name=laoqi&age=40"
  • pathname2url(path):將本地路徑轉(zhuǎn)換成 url 路徑
  • url2pathname(path):將 url 路徑轉(zhuǎn)換成本地路徑

看例子就更明白了:

>>> du = "http://www.itdiffer.com/name=python book"
>>> urllib.quote(du)
'http%3A//www.itdiffer.com/name%3Dpython%20book'
>>> urllib.quote_plus(du)
'http%3A%2F%2Fwww.itdiffer.com%2Fname%3Dpython+book'

注意看空格的變化,一個(gè)被編碼成 %20,另外一個(gè)是 +

再看解碼的,假如在 google 中搜索零基礎(chǔ) Python,結(jié)果如下圖:

http://wiki.jikexueyuan.com/project/start-learning-python/images/22501.jpg" alt="" />

我的教程可是在這次搜索中排列第一個(gè)哦。

這不是重點(diǎn),重點(diǎn)是看 url,它就是用 + 替代空格了。

>>> dup = urllib.quote_plus(du)
>>> urllib.unquote_plus(dup)
'http://www.itdiffer.com/name=Python book'

從解碼效果來看,比較完美地逆過程。

>>> urllib.urlencode({"name":"qiwsir","web":"itdiffer.com"})
'web=itdiffer.com&name=qiwsir'

這個(gè)在編程中,也會(huì)用到,特別是開發(fā)網(wǎng)站時(shí)候。

urlretrieve()

雖然 urlopen() 能夠建立類文件對(duì)象,但是,那還不等于將遠(yuǎn)程文件保存在本地存儲(chǔ)器中,urlretrieve() 就是滿足這個(gè)需要的。先看實(shí)例:

>>> import urllib
>>> urllib.urlretrieve("http://www.itdiffer.com/images/me.jpg","me.jpg")
('me.jpg', <httplib.HTTPMessage instance at 0xb6ecb6cc>)
>>> 

me.jpg 是一張存在于服務(wù)器上的圖片,地址是:http://www.itdiffer.com/images/me.jpg,把它保存到本地存儲(chǔ)器中,并且仍舊命名為 me.jpg。注意,如果只寫這個(gè)名字,表示存在啟動(dòng) Python 交互模式的那個(gè)目錄中,否則,可以指定存儲(chǔ)具體目錄和文件名。

urllib官方文檔中有一大段相關(guān)說明,讀者可以去認(rèn)真閱讀。這里僅簡(jiǎn)要介紹一下相關(guān)參數(shù)。

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

  • url:文件所在的網(wǎng)址
  • filename:可選。將文件保存到本地的文件名,如果不指定,urllib 會(huì)生成一個(gè)臨時(shí)文件來保存
  • reporthook:可選。是回調(diào)函數(shù),當(dāng)鏈接服務(wù)器和相應(yīng)數(shù)據(jù)傳輸完畢時(shí)觸發(fā)本函數(shù)
  • data:可選。如果用 post 方式所發(fā)出的數(shù)據(jù)

函數(shù)執(zhí)行完畢,返回的結(jié)果是一個(gè)元組(filename, headers),filename 是保存到本地的文件名,headers 是服務(wù)器響應(yīng)頭信息。

#!/usr/bin/env Python
# coding=utf-8

import urllib

def go(a,b,c):
    per = 100.0 * a * b / c
    if per > 100:
        per = 100
    print "%.2f%%" % per

url = "http://youxi.66wz.com/uploads/1046/1321/11410192.90d133701b06f0cc2826c3e5ac34c620.jpg"
local = "/home/qw/Pictures/g.jpg"
urllib.urlretrieve(url, local, go)

這段程序就是要下載指定的圖片,并且保存為本地指定位置的文件,同時(shí)要顯示下載的進(jìn)度。上述文件保存之后,執(zhí)行,顯示如下效果:

$ Python 22501.py 
0.00%
8.13%
16.26%
24.40%
32.53%
40.66%
48.79%
56.93%
65.06%
73.19%
81.32%
89.46%
97.59%
100.00%

到相應(yīng)目錄中查看,能看到與網(wǎng)上地址一樣的文件。我這里就不對(duì)結(jié)果截圖了,唯恐少部分讀者鼻子流血。

urllib2

urllib2 是另外一個(gè)模塊,它跟 urllib 有相似的地方——都是對(duì) url 相關(guān)的操作,也有不同的地方。關(guān)于這方面,有一篇文章講的不錯(cuò):Python: difference between urllib and urllib2

我選取一段,供大家參考:

urllib2 can accept a Request object to set the headers for a URL request, urllib accepts only a URL. That means, you cannot masquerade your User Agent string etc.

urllib provides the urlencode method which is used for the generation of GET query strings, urllib2 doesn't have such a function. This is one of the reasons why urllib is often used along with urllib2.

所以,有時(shí)候兩個(gè)要同時(shí)使用,urllib 模塊和 urllib2 模塊有的方法可以相互替代,有的不能。看下面的屬性方法列表就知道了。

>>> dir(urllib2)
['AbstractBasicAuthHandler', 'AbstractDigestAuthHandler', 'AbstractHTTPHandler', 'BaseHandler', 'CacheFTPHandler', 'FTPHandler', 'FileHandler', 'HTTPBasicAuthHandler', 'HTTPCookieProcessor', 'HTTPDefaultErrorHandler', 'HTTPDigestAuthHandler', 'HTTPError', 'HTTPErrorProcessor', 'HTTPHandler', 'HTTPPasswordMgr', 'HTTPPasswordMgrWithDefaultRealm', 'HTTPRedirectHandler', 'HTTPSHandler', 'OpenerDirector', 'ProxyBasicAuthHandler', 'ProxyDigestAuthHandler', 'ProxyHandler', 'Request', 'StringIO', 'URLError', 'UnknownHandler', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__version__', '_cut_port_re', '_opener', '_parse_proxy', '_safe_gethostbyname', 'addinfourl', 'base64', 'bisect', 'build_opener', 'ftpwrapper', 'getproxies', 'hashlib', 'httplib', 'install_opener', 'localhost', 'mimetools', 'os', 'parse_http_list', 'parse_keqv_list', 'posixpath', 'proxy_bypass', 'quote', 'random', 'randombytes', 're', 'request_host', 'socket', 'splitattr', 'splithost', 'splitpasswd', 'splitport', 'splittag', 'splittype', 'splituser', 'splitvalue', 'sys', 'time', 'toBytes', 'unquote', 'unwrap', 'url2pathname', 'urlopen', 'urlparse', 'warnings']

比較常用的比如 urlopen() 跟 urllib.open() 是完全類似的。

Request 類

正如前面區(qū)別 urllib 和 urllib2 所講,利用 urllib2 模塊可以建立一個(gè) Request 對(duì)象。方法就是:

>>> req = urllib2.Request("http://www.itdiffer.com")

建立了 Request 對(duì)象之后,它的最直接應(yīng)用就是可以作為 urlopen() 方法的參數(shù)

>>> response = urllib2.urlopen(req)
>>> page = response.read()
>>> print page

因?yàn)榕c前面的 urllib.open("http://www.itdiffer.com") 結(jié)果一樣,就不浪費(fèi)篇幅了。

但是,如果 Request 對(duì)象僅僅局限于此,似乎還沒有什么太大的優(yōu)勢(shì)。因?yàn)閯偛诺脑L問僅僅是滿足以 get 方式請(qǐng)求頁面,并建立類文件對(duì)象。如果是通過 post 向某地址提交數(shù)據(jù),也可以建立 Request 對(duì)象。

import urllib    
import urllib2    

url = 'http://www.itdiffer.com/register.py'    

values = {'name' : 'qiwsir',    
          'location' : 'China',    
          'language' : 'Python' }    

data = urllib.urlencode(values)     # 編碼  
req = urllib2.Request(url, data)    # 發(fā)送請(qǐng)求同時(shí)傳 data 表單  
response = urllib2.urlopen(req)     #接受反饋的信息  
the_page = response.read()          #讀取反饋的內(nèi)容

注意,讀者不能照抄上面的程序,然后運(yùn)行代碼。因?yàn)槟莻€(gè) url 中沒有相應(yīng)的接受客戶端 post 上去的 data 的程序文件。上面的代碼只是以一個(gè)例子來顯示 Request 對(duì)象的另外一個(gè)用途,還有就是在這個(gè)例子中是以 post 方式提交數(shù)據(jù)。

在網(wǎng)站中,有的會(huì)通過 User-Agent 來判斷訪問者是瀏覽器還是別的程序,如果通過別的程序訪問,它有可能拒絕。這時(shí)候,我們編寫程序去訪問,就要設(shè)置 headers 了。設(shè)置方法是:

user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }

然后重新建立 Request 對(duì)象:

req = urllib2.Request(url, data, headers)    

再用 urlopen() 方法訪問:

response = urllib2.urlopen(req) 

除了上面演示之外,urllib2 模塊的東西還很多,比如還可以:

  • 設(shè)置 HTTP Proxy
  • 設(shè)置 Timeout 值
  • 自動(dòng) redirect
  • 處理 cookie

等等。這些內(nèi)容不再一一介紹,當(dāng)需要用到的時(shí)候可以查看文檔或者 google。


總目錄   |   上節(jié):標(biāo)準(zhǔn)庫(kù)(5)   |   下節(jié):標(biāo)準(zhǔn)庫(kù)(7)

如果你認(rèn)為有必要打賞我,請(qǐng)通過支付寶:qiwsir@126.com,不勝感激。

上一篇:函數(shù)練習(xí)下一篇:字符串(3)