轉載請註明:@小五義http://www.cnblogs.com/xiaowuyi
6.1 最簡單的爬蟲
網路爬蟲是一個自動提取網頁的程式,它為搜尋引擎從全球資訊網上下載網頁,是搜尋引擎的重要組成。python的urllib\urllib2等模組很容易實現這一功能,下面的例子實現的是對baidu首頁的下載。具體代碼如下:
import urllib2page=urllib2.urlopen("http://www.baidu.com")print page.read()
6.2 提交表單資料
(1)用GET方法提交資料
提交表單的GET方法是把表單資料編碼至URL。在給出請示的頁面後,加上問號,接著是表單的元素。如在百度中搜尋“馬伊琍”得到url為http://www.baidu.com/s?wd=%E9%A9%AC%E4%BC%8A%E7%90%8D&pn=100&rn=20&ie=utf-8&usm=4&rsv_page=1。其中?後面為表單元素。wd=%E9%A9%AC%E4%BC%8A%E7%90%8D表示搜尋的詞是“馬伊琍”,pn表示從第100條資訊所在頁開始顯示(感覺是這樣,我試了幾次,當寫100時,從其所在頁顯示,但如果寫10,就是從第1頁顯示),rn=20表示每頁顯示20條,ie=utf-8表示編碼格式,usm=4沒明白是什麼意思,換了1、2、3試了下,沒發現什麼變化,rsv_page=1表示第幾頁。如果要下載以上頁面比較簡單的方法是直接用上面的網址進行提取。如代碼:
import urllib2keyword=urllib.quote('馬伊琍')page=urllib2.urlopen("http://www.baidu.com/s?wd="+keyword+"&pn=100&rn=20&ie=utf-8&usm=4&rsv_page=1")print page.read()
(2)用post方法提交
GET方法中,資料是被加到URL上,這種方法資料量要求不大,如果需要交換大量資料的時間,POST方法是一個很好的方法。這裡以前段時間寫的部落格《python類比163登陸擷取郵件清單》為例,具體代碼不在列出,詳見地址:http://www.cnblogs.com/xiaowuyi/archive/2012/05/21/2511428.html。
6.3 urllib,urllib2,httplib,mechanize的介紹
6.3.1urllib模組(引自:http://my.oschina.net/duhaizhang/blog/68893)
urllib模組提供介面可以使我們像訪問本地檔案一樣來讀取www和ftp上的資料。模組中最重要的兩個函數分別是:urlopen()和urlretrieve()。
urllib.urlopen(url[, data[, proxies]]) :
本函數建立一個表示遠程url的類檔案對象,然後像本地檔案一樣操作這個類檔案對象來擷取遠端資料。參數url表示遠端資料的路徑,一般是網址;參數data表示以post方式提交到url的資料;參數proxies用於設定代理。urlopen返回 一個類檔案對象,返回的類檔案對象提供了如下方法:
read(), readline(), readlines(), fileno(), close():這些方法的使用方式與檔案對象完全一樣;
info():返回一個httplib.HTTPMessage對象,表示遠程伺服器返回的頭資訊;
getcode():返回Http狀態代碼。如果是http請求,200表示請求成功完成;404表示網址未找到;
geturl():返回請求的url;
#! /usr/bin/env python#coding=utf-8import urllibcontent=urllib.urlopen("http://www.baidu.com")print "http header:",content.info()print "http status:",content.getcode()print "url:",content.geturl()print "content:"for line in content.readlines(): print line
urllib.urlretrieve(url[, filename[, reporthook[, data]]]):
urlretrieve方法直接將遠端資料下載到本地。參數filename指定了儲存到本地的路徑(如果未指定該參數,urllib會產生一個臨時檔案來儲存資料);參數reporthook是一個 回呼函數,當串連上伺服器、以及相應的資料 塊傳輸完畢的時候會觸發該回調(即每下載一塊就調用一次回呼函數)。我們可以利用這個回調函 數來顯示當前的下載進度,也可以用於限速,下面的例子會展示。參數data指post到伺服器的資料。該方法返回一個包含兩個元素的元組(filename, headers),filename表示儲存到本地的路徑, header表示伺服器的回應標頭。
#! /usr/bin/env python # coding: utf-8 """下載檔案,並顯示下載進度"""import urllibdef DownCall(count,size,total_filesize): """count為已下載資料區塊個數,size為資料區塊的大小,total_filesize為檔案總大小""" per=100.0*count*size/total_filesize if per>100: per=100 print "Already download %d KB(%.2f" %(count*size/1024,per)+"%)"url="http://www.research.rutgers.edu/~rohanf/LP.pdf"localfilepath=r"C:\Users\Administrator\Desktop\download.pdf"urllib.urlretrieve(url,localfilepath,DownCall)
urllib中還提供了一些輔助方法,用於對url進行編碼、解碼。url中是不能出現一些特殊的符號的,有些符號有特殊的用途。我們知道以get方式提交資料的時候,會在url中添加key=value這樣的字串,所以在value中是不允許有'=',因此要對其進行編碼;與此同時伺服器接收到這些參數的時候,要進行解碼,還原成原始的資料。這個時候,這些輔助方法會很有用:
urllib.quote(string[, safe]):對字串進行編碼。參數safe指定了不需要編碼的字元;
urllib.unquote(string) :對字串進行解碼;
urllib.quote_plus(string[, safe]) :與urllib.quote類似,但這個方法用'+'來替換' ',而quote用'%20'來代替' '
urllib.unquote_plus(string) :對字串進行解碼;
urllib.urlencode(query[, doseq]):將dict或者包含兩個元素的元組列錶轉換成url參數。例如 字典{'name': 'dark-bull', 'age': 200}將被轉換為"name=dark-bull&age=200"
urllib.pathname2url(path):將本地路徑轉換成url路徑;
urllib.url2pathname(path):將url路徑轉換成本地路徑;
6.3.2 urllib2模組(引自:http://hankjin.blog.163.com/blog/static/3373193720105140583594/)
使用Python訪問網頁主要有三種方式: urllib, urllib2, httplib
urllib比較簡單,功能相對也比較弱,httplib簡單強大,但好像不支援session
(1)最簡單的頁面訪問
res=urllib2.urlopen(url)
print res.read()
(2)加上要get或post的資料
data={"name":"hank", "passwd":"hjz"}
urllib2.urlopen(url, urllib.urlencode(data))
(3)加上http頭
header={"User-Agent": "Mozilla-Firefox5.0"}
urllib2.urlopen(url, urllib.urlencode(data), header)
使用opener和handler
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
(4)加上session
cj = cookielib.CookieJar()
cjhandler=urllib2.HTTPCookieProcessor(cj)
opener = urllib2.build_opener(cjhandler)
urllib2.install_opener(opener)
(5)加上Basic認證
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
top_level_url = "http://www.163.com/"
password_mgr.add_password(None, top_level_url, username, password)
handler = urllib2.HTTPBasicAuthHandler(password_mgr)
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
(6) 使用代理
proxy_support = urllib2.ProxyHandler({"http":"http://1.2.3.4:3128/"})
opener = urllib2.build_opener(proxy_support)
urllib2.install_opener(opener)
(7) 設定逾時
socket.setdefaulttimeout(5)
6.3.3 httplib模組(引自:http://hi.baidu.com/avengert/item/be5daec8517b12ddee183b81)
httplib 是 python中http 協議的用戶端實現,可以使用該模組來與 HTTP 伺服器進行互動。httplib的內容不是很多,也比較簡單。以下是一個非常簡單的例子,使用httplib擷取google首頁的html:
#coding=gbk import httplib conn = httplib.HTTPConnection("www.google.cn") conn.request('get', '/') print conn.getresponse().read() conn.close()
下面詳細介紹httplib提供的常用類型和方法。
httplib.HTTPConnection ( host [ , port [ , strict [ , timeout ]]] )
HTTPConnection類的建構函式,表示一次與伺服器之間的互動,即請求/響應。參數host表示伺服器主機,如:www.csdn.net;port為連接埠號碼,預設值為80; 參數strict的 預設值為false, 表示在無法解析伺服器返回的狀態行時( status line) (比較典型的狀態行如: HTTP/1.0 200 OK ),是否拋BadStatusLine 異常;選擇性參數timeout 表示逾時時間。
HTTPConnection提供的方法:
HTTPConnection.request ( method , url [ , body [ , headers ]] )
調用request 方法會向伺服器發送一次請求,method 表示請求的方法,常用有方法有get 和post ;url 表示請求的資源的url ;body 表示提交到伺服器的資料,必須是字串(如果method 是"post" ,則可以把body 理解為html 表單中的資料);headers 表示請求的http 頭。
HTTPConnection.getresponse ()
擷取Http 響應。返回的對象是HTTPResponse 的執行個體,關於HTTPResponse 在下面 會講解。
HTTPConnection.connect ()
串連到Http 伺服器。
HTTPConnection.close ()
關閉與伺服器的串連。
HTTPConnection.set_debuglevel ( level )
設定高度的層級。參數level 的預設值為0 ,表示不輸出任何調試資訊。
httplib.HTTPResponse
HTTPResponse表示伺服器對用戶端請求的響應。往往通過調用HTTPConnection.getresponse()來建立,它有如下方法和屬性:
HTTPResponse.read([amt])
擷取響應的訊息體。如果請求的是一個普通的網頁,那麼該方法返回的是頁面的html。選擇性參數amt表示從響應流中讀取指定位元組的資料。
HTTPResponse.getheader(name[, default])
擷取回應標頭。Name表示頭域(header field)名,選擇性參數default在頭網域名稱不存在的情況下作為預設值返回。
HTTPResponse.getheaders()
以列表的形式返回所有的頭資訊。
HTTPResponse.msg
擷取所有的回應標頭資訊。
HTTPResponse.version
擷取伺服器所使用的http協議版本。11表示http/1.1;10表示http/1.0。
HTTPResponse.status
擷取響應的狀態代碼。如:200表示請求成功。
HTTPResponse.reason
返回伺服器處理請求的結果說明。一般為”OK”
下面通過一個例子來熟悉HTTPResponse中的方法:
#coding=gbk import httplib conn = httplib.HTTPConnection("www.g.cn", 80, False) conn.request('get', '/', headers = {"Host": "www.google.cn", "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1) Gecko/20090624 Firefox/3.5", "Accept": "text/plain"}) res = conn.getresponse() print 'version:', res.version print 'reason:', res.reason print 'status:', res.status print 'msg:', res.msg print 'headers:', res.getheaders() #html #print '\n' + '-' * 50 + '\n' #print res.read() conn.close()
Httplib模組中還定義了許多常量,如:
Httplib. HTTP_PORT 的值為80,表示預設的連接埠號碼為80;
Httplib.OK 的值為200,表示請求成功返回;
Httplib. NOT_FOUND 的值為40表示請求的資源不存在;
可以通過httplib.responses 查詢相關變數的含義,如:
Print httplib.responses[httplib.NOT_FOUND]
6.3.4 mechanize
mechanize沒有找到比較完整的介紹,自己寫了一個簡單的例子如下。
# -*- coding: cp936 -*-import time,stringimport mechanize,urllibfrom mechanize import Browserurlname=urllib.quote('馬伊琍')br=Browser()br.set_handle_robots(False) ##ignore the robots.txturlhttp=r'http://www.baidu.com/s?'+urlname+"&pn=10&rn=20&ie=utf-8&usm=4&rsv_page=1"response=br.open(urlhttp)filename='temp.html'f=open(filename,'w')f.write(response.read())f.close()