## urllib
urllib模塊用于讀取來自網上(服務器上)的數據,比如不少人用python做爬蟲程序,就可以使用這個模塊。先看一個簡單例子:
~~~
>>> import urllib
>>> itdiffer = urllib.urlopen("http://www.itdiffer.com")
~~~
這樣就已經把我的網站[www.itdiffer.com](http://www.itdiffer.com/)首頁的內容拿過來了,得到了一個類似文件的對象。接下來的操作跟操作一個文件一樣(如果忘記了文件怎么操作,可以參考:[《文件(1)](https://github.com/qiwsir/StarterLearningPython/blob/master/126.md))
~~~
>>> print itdiffer.read()
<!DOCTYPE HTML>
<html>
<head>
<title>I am Qiwsir</title>
....//因為內容太多,下面就省略了
~~~
就這么簡單,完成了對一個網頁的抓取。當然,如果你真的要做爬蟲程序,還不是僅僅如此。這里不介紹爬蟲程序如何編寫,僅說明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']
~~~
選幾個常用的介紹,其它的如果讀者用到,可以通過查看文檔了解。
**urlopen()**
urlopen()主要用于打開url文件,然后就獲得指定url的數據,接下來就如同在本地操作文件那樣來操作。
> 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.
得到的對象被叫做類文件。從名字中也可以理解后面的操作了。先對參數說明一下:
* url:遠程數據的路徑,常常是網址
* data:如果使用post方式,這里就是所提交的數據
* proxies:設置代理
關于參數的詳細說明,還可以參考[python的官方文檔](https://docs.python.org/2/library/urllib.html),這里僅演示最常用的,如前面的例子那樣。
當得到了類文件對象之后,就可以對它進行操作。變量itdiffer引用了得到的類文件對象,通過它查看:
~~~
>>> dir(itdiffer)
['__doc__', '__init__', '__iter__', '__module__', '__repr__', 'close', 'code', 'fileno', 'fp', 'getcode', 'geturl', 'headers', 'info', 'next', 'read', 'readline', 'readlines', 'url']
~~~
讀者從這個結果中也可以看出,這個類文件對象也是可迭代的。常用的方法:
* read(),readline(),readlines(),fileno(),close():都與文件操作一樣,這里不再贅述。可以參考前面有關文件章節
* info():返回頭信息
* getcode():返回http狀態碼
* geturl():返回url
簡單舉例:
~~~
>>> itdiffer.info()
<httplib.HTTPMessage instance at 0xb6eb3f6c>
>>> itdiffer.getcode()
200
>>> itdiffer.geturl()
'http://www.itdiffer.com'
~~~
更多情況下,已經建立了類文件對象,通過對文件操作方法,獲得想要的數據。
**對url編碼、解碼**
url對其中的字符有嚴格要求,不許可某些特殊字符,這就要對url進行編碼和解碼了。這個在進行web開發的時候特別要注意。urllib模塊提供這種功能。
* quote(string[, safe]):對字符串進行編碼。參數safe指定了不需要編碼的字符
* urllib.unquote(string) :對字符串進行解碼
* quote_plus(string [ , safe ] ) :與urllib.quote類似,但這個方法用'+'來替換空格`' '`,而quote用'%20'來代替空格
* unquote_plus(string ) :對字符串進行解碼;
* urllib.urlencode(query[, doseq]):將dict或者包含兩個元素的元組列表轉換成url參數。例如{'name': 'laoqi', 'age': 40}將被轉換為"name=laoqi&age=40"
* pathname2url(path):將本地路徑轉換成url路徑
* url2pathname(path):將url路徑轉換成本地路徑
看例子就更明白了:
~~~
>>> 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'
~~~
注意看空格的變化,一個被編碼成`%20`,另外一個是`+`
再看解碼的,假如在google中搜索`零基礎 python`,結果如下圖:
[](https://github.com/qiwsir/StarterLearningPython/blob/master/2images/22501.jpg)
我的教程可是在這次搜索中排列第一個哦。
這不是重點,重點是看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'
~~~
這個在編程中,也會用到,特別是開發網站時候。
**urlretrieve()**
雖然urlopen()能夠建立類文件對象,但是,那還不等于將遠程文件保存在本地存儲器中,urlretrieve()就是滿足這個需要的。先看實例:
~~~
>>> import urllib
>>> urllib.urlretrieve("http://www.itdiffer.com/images/me.jpg","me.jpg")
('me.jpg', <httplib.HTTPMessage instance at 0xb6ecb6cc>)
>>>
~~~
me.jpg是一張存在于服務器上的圖片,地址是:[http://www.itdiffer.com/images/me.jpg,把它保存到本地存儲器中,并且仍舊命名為me.jpg。注意,如果只寫這個名字,表示存在啟動python交互模式的那個目錄中,否則,可以指定存儲具體目錄和文件名。](http://www.itdiffer.com/images/me.jpg%EF%BC%8C%E6%8A%8A%E5%AE%83%E4%BF%9D%E5%AD%98%E5%88%B0%E6%9C%AC%E5%9C%B0%E5%AD%98%E5%82%A8%E5%99%A8%E4%B8%AD%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BB%8D%E6%97%A7%E5%91%BD%E5%90%8D%E4%B8%BAme.jpg%E3%80%82%E6%B3%A8%E6%84%8F%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%8F%AA%E5%86%99%E8%BF%99%E4%B8%AA%E5%90%8D%E5%AD%97%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%AD%98%E5%9C%A8%E5%90%AF%E5%8A%A8python%E4%BA%A4%E4%BA%92%E6%A8%A1%E5%BC%8F%E7%9A%84%E9%82%A3%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%AD%EF%BC%8C%E5%90%A6%E5%88%99%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E5%AD%98%E5%82%A8%E5%85%B7%E4%BD%93%E7%9B%AE%E5%BD%95%E5%92%8C%E6%96%87%E4%BB%B6%E5%90%8D%E3%80%82)
在[urllib官方文檔](https://docs.python.org/2/library/urllib.html)中有一大段相關說明,讀者可以去認真閱讀。這里僅簡要介紹一下相關參數。
`urllib.urlretrieve(url[, filename[, reporthook[, data]]])`
* url:文件所在的網址
* filename:可選。將文件保存到本地的文件名,如果不指定,urllib會生成一個臨時文件來保存
* reporthook:可選。是回調函數,當鏈接服務器和相應數據傳輸完畢時觸發本函數
* data:可選。如果用post方式所發出的數據
函數執行完畢,返回的結果是一個元組(filename, headers),filename是保存到本地的文件名,headers是服務器響應頭信息。
~~~
#!/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)
~~~
這段程序就是要下載指定的圖片,并且保存為本地指定位置的文件,同時要顯示下載的進度。上述文件保存之后,執行,顯示如下效果:
~~~
$ 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%
~~~
到相應目錄中查看,能看到與網上地址一樣的文件。我這里就不對結果截圖了,唯恐少部分讀者鼻子流血。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/225.md#urllib2)urllib2
urllib2是另外一個模塊,它跟urllib有相似的地方——都是對url相關的操作,也有不同的地方。關于這方面,有一篇文章講的不錯:[Python: difference between urllib and urllib2](http://www.hacksparrow.com/python-difference-between-urllib-and-urllib2.html)
我選取一段,供大家參考:
> 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.
所以,有時候兩個要同時使用,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類**
正如前面區別urllib和urllib2所講,利用urllib2模塊可以建立一個Request對象。方法就是:
~~~
>>> req = urllib2.Request("http://www.itdiffer.com")
~~~
建立了Request對象之后,它的最直接應用就是可以作為urlopen()方法的參數
~~~
>>> response = urllib2.urlopen(req)
>>> page = response.read()
>>> print page
~~~
因為與前面的`urllib.open("http://www.itdiffer.com")`結果一樣,就不浪費篇幅了。
但是,如果Request對象僅僅局限于此,似乎還沒有什么太大的優勢。因為剛才的訪問僅僅是滿足以get方式請求頁面,并建立類文件對象。如果是通過post向某地址提交數據,也可以建立Request對象。
~~~
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) # 發送請求同時傳data表單
response = urllib2.urlopen(req) #接受反饋的信息
the_page = response.read() #讀取反饋的內容
~~~
注意,讀者不能照抄上面的程序,然后運行代碼。因為那個url中沒有相應的接受客戶端post上去的data的程序文件。上面的代碼只是以一個例子來顯示Request對象的另外一個用途,還有就是在這個例子中是以post方式提交數據。
在網站中,有的會通過User-Agent來判斷訪問者是瀏覽器還是別的程序,如果通過別的程序訪問,它有可能拒絕。這時候,我們編寫程序去訪問,就要設置headers了。設置方法是:
~~~
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }
~~~
然后重新建立Request對象:
~~~
req = urllib2.Request(url, data, headers)
~~~
再用urlopen()方法訪問:
~~~
response = urllib2.urlopen(req)
~~~
除了上面演示之外,urllib2模塊的東西還很多,比如還可以:
* 設置HTTP Proxy
* 設置Timeout值
* 自動redirect
* 處理cookie
等等。這些內容不再一一介紹,當需要用到的時候可以查看文檔或者google。
- 第零章 預備
- 關于Python的故事
- 從小工到專家
- Python安裝
- 集成開發環境
- 第壹章 基本數據類型
- 數和四則運算
- 除法
- 常用數學函數和運算優先級
- 寫一個簡單的程序
- 字符串(1)
- 字符串(2)
- 字符串(3)
- 字符串(4)
- 字符編碼
- 列表(1)
- 列表(2)
- 列表(3)
- 回顧list和str
- 元組
- 字典(1)
- 字典(2)
- 集合(1)
- 集合(2)
- 第貳章 語句和文件
- 運算符
- 語句(1)
- 語句(2)
- 語句(3)
- 語句(4)
- 語句(5)
- 文件(1)
- 文件(2)
- 迭代
- 練習
- 自省
- 第叁章 函數
- 函數(1)
- 函數(2)
- 函數(3)
- 函數(4)
- 函數練習
- 第肆章 類
- 類(1)
- 類(2)
- 類(3)
- 類(4)
- 類(5)
- 多態和封裝
- 特殊方法(1)
- 特殊方法(2)
- 迭代器
- 生成器
- 上下文管理器
- 第伍章 錯誤和異常
- 錯誤和異常(1)
- 錯誤和異常(2)
- 錯誤和異常(3)
- 第陸章 模塊
- 編寫模塊
- 標準庫(1)
- 標準庫(2)
- 標準庫(3)
- 標準庫(4)
- 標準庫(5)
- 標準庫(6)
- 標準庫(7)
- 標準庫(8)
- 第三方庫
- 第柒章 保存數據
- 將數據存入文件
- mysql數據庫(1)
- MySQL數據庫(2)
- mongodb數據庫(1)
- SQLite數據庫
- 電子表格
- 第捌章 用Tornado做網站
- 為做網站而準備
- 分析Hello
- 用tornado做網站(1)
- 用tornado做網站(2)
- 用tornado做網站(3)
- 用tornado做網站(4)
- 用tornado做網站(5)
- 用tornado做網站(6)
- 用tornado做網站(7)
- 第玖章 科學計算
- 為計算做準備
- Pandas使用(1)
- Pandas使用(2)
- 處理股票數據
- 附:網絡文摘
- 如何成為Python高手
- ASCII、Unicode、GBK和UTF-8字符編碼的區別聯系