urllib 模塊是一個高級的 web 交流庫,其核心功能就是模仿web瀏覽器等客戶端,去請求相應的資源,並返回一個類文件對象。urllib 支持各種 web 協議,例如:HTTP、FTP、Gopher;同時也支持對本地文件進行訪問。但一般而言多用來進行爬蟲的編寫,而下麵的內容也是圍繞著如何使用 u ...
urllib 模塊是一個高級的 web 交流庫,其核心功能就是模仿web瀏覽器等客戶端,去請求相應的資源,並返回一個類文件對象。urllib 支持各種 web 協議,例如:HTTP、FTP、Gopher;同時也支持對本地文件進行訪問。但一般而言多用來進行爬蟲的編寫,而下麵的內容也是圍繞著如何使用 urllib 庫去編寫簡單的爬蟲。另外,如果要爬取 js 動態生成的東西, 如 js 動態載入的圖片,還需要一些高級的技巧,這裡的例子都是針對於靜態的 html 網頁的。
下麵的說明都是針對於 python2.7 版本而言的,版本間存在差距,具體參考官方手冊。
首先,如果我需要寫一個爬蟲,去爬取一個網站的圖片的話,可以分為以下幾步:
當然,你也可以將爬到的數據進行各種處理分析,例如你可以寫一個比價網站,去各種網站獲取報價,然後整合到一起。所以,將上面的佈置拓展到所有的爬蟲後:
下麵我們按照這個通用的佈置,學習每一步都應該怎麼做。
1.打開目標網站
urllib.urlopen(url[, data[, proxies[, context]]])
去遠程請求響應的 url,並返回一個類文件對象。(註意,此處已經發起了遠程請求,也就是進行了聯網操作,有數量流量)
url : 一個完整的遠程資源路徑,一般是一個網站。(註意,要包含協議頭,例如:http://www.baidu.com/,此處的 http:// 不能省略)
如果該URL沒有指明協議類型,或者其協議標識符為file:,則該函數會打開本地文件。如果無法打開遠程地址,將觸發 IOError 異常。
data : 如果使用的是 http:// 協議,這是一個可選的參數,用於指定一個 POST 請求(預設使用的是 GET 方法)。這個參數必須使用標準的 application/x-www-form-urlencoded 格式。我們可以使用 urlencode() 方法來快速生成。
proxies : 設置代理,有需要的參照官方文檔。下麵給出官網的例子:
# Use http://www.someproxy.com:3128 for HTTP proxying proxies = {'http': 'http://www.someproxy.com:3128'} filehandle = urllib.urlopen(some_url, proxies=proxies) # Don't use any proxies filehandle = urllib.urlopen(some_url, proxies={}) # Use proxies from environment - both versions are equivalent filehandle = urllib.urlopen(some_url, proxies=None) filehandle = urllib.urlopen(some_url)
context : 在用 HTTPS 連接時,這個參數要設置為 ssl.SSLContext
的實例,用於配置 SSL 。
一般而言,我們只需要設置 url 參數就可以了。
例如:
f = urllib.urlopen('http://www.baidu.com/')
這樣我能就能夠得到一個類文件對象了,然後就可以對這個類文件對象進行各種讀取操作了。
2.操作類文件對象
下麵的方法和文件操作中的一致,下麵列舉出來,詳情請參考我在python文件操作中的解釋:
1. read([size]) -> read at most size bytes, returned as a string.
讀取整個文件,將讀取結果返回一個字元串對象
2. readline([size]) -> next line from the file, as a string.
讀取一行,將讀取結果返回一個字元串對象
3. readlines([size]) -> list of strings, each a line from the file.
讀取整個文件,將每一行封裝成列表中的元素,返回一個列表。
4. readinto() -> Undocumented. Don't use this; it may go away.
一個可以無視的將要廢棄的方法
5. close() -> None or (perhaps) an integer. Close the file.
關閉文件,返回None或者一個表示關閉狀態的整數。
另外:也可以和文件對象一樣直接進行迭代操作。
除了以上和文件操作中用法一樣的方法之外,還有以下特殊的方法:
1. info()
返迴文件信息,對於 http 協議來說,返回的是響應報文中的報文頭。
例子:
f = urllib.urlopen('http://www.so.com/') print f.info()
2. geturl()
返回當前頁面的真正的 url ,針對於網站伺服器在進行重定向以後,我們可以用它來獲取重定向後的頁面。
3. getcode()
返回當前請求的狀態碼,如成功請求的狀態碼就是 200 。如果不是使用 http 協議打開的,就返回 None。
3.操作讀取後的網頁源碼
這個部分就和文件操作一樣了,但多數情況下會和 re 模塊配合起來進行數據篩選,例如:
f = urllib.urlopen('http://www.baidu.com/') b = f.read() p = re.compile(r'<img.*?src="//(.*?\.(?:jpg|gif|png))".*?>', re.I) result = p.findall(b) print result
嘗試在百度的首頁爬取圖片的地址,當然還有很多改進的地方,這裡中做演示用。
關於python中的正則 re 模塊的使用這裡就不再重覆了。
4.下載相應資源
在我們通過正則篩選出我們相要的圖片的 url 之後,就可以開始下載了,在 urllib 中提供了相應的下載函數。
1. urllib.urlretrieve(url[, filename[, reporthook[, data]]])
將給定的 url 下載為本地文件,如果 url 指向的是本地的文件,或者是一個有效的緩存對象,那麼將不會下載(註意,這裡的存在是指下載的目錄里有相同的文件了)。返回一個元祖(filename, headers),其中filename值的是本地保存的文件名,header指的是上面 info() 方法返回的對象。
url : 目標 url 。
filename : 下載到本地後保存的文件名, 可以是決對路徑或相對路徑形式。如果沒有給,將緩存到一個臨時文件夾中。
reporthook:一個回調函數,方法會在連接建立時和下載完成時調用這個函數。同時會向函數傳遞三個參數:1.目前為止下載了多少數據塊;2.數據塊的大小(單位是位元組);3.文件的總大小;
data:如果使用的是 http:// 協議,這是一個可選的參數,用於指定一個 POST 請求(預設使用的是 GET 方法)。這個參數必須使用標準的 application/x-www-form-urlencoded 格式。我們可以使用 urlencode()來快速生成。
2. urllib.urlcleanup()
Clear the cache that may have been built up by previous calls to urlretrieve()
.
清除先前由 urlretrieve()
建立的緩存
。
其他常用模塊內置方法:
1. urllib.quote(string[, safe])
將 string 編碼成 url 格式,safe 指定不受影響的字元(預設 safe='/')。
因為 url 的編碼和我們常用的 ASCII 並不同,例如我們常用的空格在 ASCII 中: 'scolia good' 直接現實一個空白字元,而在 url 中: 'scolia%20good' ,原本的空白字元變成了 %20 。
其轉換規則為:
逗號,下劃線,句號,斜線和字母數字這類符號是不需要轉化。其他的則均需要轉換。另外, 那些不被允許的字元前邊會被加上百分號(%)同時轉換成 16 進位,例如:“%xx”,“xx”代表這個字母的 ASCII 碼的十六進位值。
例子:
f = urllib.quote('scolia good') print f
2. urllib.quote_plus(string[, safe])
和上面的幾乎一樣,只是不轉換空白字元,而將其用 + 號替換。
例子:
f = urllib.quote_plus('scolia good') print f
3. urllib.unquote(string)
將 url 重新轉碼回去,是上面操作的urllib.quote(string[, safe])逆運算。
4. unquote_plus(string)
同上,是urllib.quote_plus(string[, safe])的逆運算。
5. urllib.urlencode(query[, doseq])
將一個python的字典快速轉換為一個請求的格式,用於上面的 data 屬性。
例子:
aDict = {'name': 'Georgina Garcia', 'hmdir': '~ggarcia'} print urllib.urlencode(aDict)
這裡註意:一旦設置的 data,就意味使用 POST 請求,如果要使用 GET 請求,請在 url 的後面加上 ? 號,再將轉換好的數據放進去。
例如:
GET方法:
import urllib params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0}) f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params) print f.read()
POST方法:
import urllib params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0}) f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query", params) print f.read()
6. urllib.pathname2url(path)
將本地路徑名轉換成 url 風格的路徑名,這不會產生一個完整的URL,而且得到的結果已經調用了 quote() 方法進行了處理。
例子:
a = r'd:\abc\def\123.txt' print urllib.pathname2url(a)
7. urllib.url2pathname(path)
將 url 風格的路徑轉換為本地路徑風格,是上面方法的逆運算。
a = r'www.xxx.com/12%203/321/' print urllib.url2pathname(a)
同樣的調用了 quote() 方法進行了處理
其他的內容請參考官方文檔:https://docs.python.org/2/library/urllib.html