首先,推薦兩個關於python爬蟲不錯的博客:Python爬蟲入門教程專欄 和 Python爬蟲學習系列教程。寫的都非常不錯,我學習到了很多東西!在此,我就我看到的學到的進行總結一下! 爬蟲就是一個不斷的去抓去網頁的程式,根據我們的需要得到我們想要的結果!但我們又要讓伺服器感覺是我們人在通過瀏...
首先,推薦兩個關於python爬蟲不錯的博客:Python爬蟲入門教程專欄 和 Python爬蟲學習系列教程 。寫的都非常不錯,我學習到了很多東西!在此,我就我看到的學到的進行總結一下!
爬蟲就是一個不斷的去抓去網頁的程式,根據我們的需要得到我們想要的結果!但我們又要讓伺服器感覺是我們人在通過瀏覽器瀏覽不是程式所為!歸根到底就是我們通過程式訪問網站得到html代碼,然後分析html代碼獲取有效內容的過程。下麵讓我們從最簡單的爬蟲開始:
爬取一個頁面源代碼
在python中,抓取網頁的庫是urllib2。下麵看一個最簡單的例子:
1 import urllib2 2 response = urllib2.urlopen('http://www.baidu.com/') 3 html = response.read() 4 print html
執行完成後你會發現視窗中打出了一堆代碼,其實就是百度主頁的html代碼!(抵制百度!!!)
我們來看一下urlopen的用法:
1 >>> help(urllib2.urlopen) 2 Help on function urlopen in module urllib2: 3 4 urlopen(url, data=None, timeout=<object object>, cafile=None, capath=None, cadefault=False, context=None)
第一個參數為url,第二個為要發送的數據,第三個是超時時間。其餘的我們一般不用,就不解釋了!第二三個參數不是必須的,因為都有預設值,data預設值為None,timeout預設值為socket._GLOBAL_DEFAUTL_TIMEOUT。傳入url之後,我們得到一個response對象,返回的信息就在這裡面!通過response.read()獲取裡面的內容。同樣的我們可以構造一個Request類,作為參數傳入urlopen中,這個Request類中就包含url,data,timeout等內容。上面的代碼我們可以寫成這樣:
1 import urllib2 2 3 request = urllib2.Request("http://www.baidu.com") 4 response = urllib2.urlopen(request) 5 print response.read()
這樣是不是很清晰明瞭了?在構建Request的時候我們通常會加入很多內容,我們發出一個請求,伺服器給我們一個響應。一個簡單的爬蟲就這樣起飛了!
POST和GET數據傳送
平常我們在瀏覽網頁的時候難免涉及到登錄註冊,填寫表單,或者跳轉到某個頁面,這時候我們要跟伺服器進行交互,向伺服器發送數據,發送數據的方式呢就是Post和Get,兩者的區別在於GET方式直接以鏈接的形式訪問,鏈接中包含所有的參數,如:http://www.baidu.com/shit?result=true 其中 result=true就是Get傳遞的數據,POST相當於Get就安全多了,它不會在鏈接上顯示所有參數。
Post方式:
1 import urllib 2 import urllib2 3 4 values = {} 5 values['username'] = "[email protected]" 6 values['password'] = "******" 7 data = urllib.urlencode(values) 8 url = "http://www.xxx.com/login?from=http://xxx/loginInfo" 9 request = urllib2.Request(url,data) 10 response = urllib2.urlopen(request) 11 print response.read()
在上面的代碼中,我們創建了一個字典values,設置了username和password的值,然後通過urlencode函數將字典進行轉碼,命名為data,然後用url和data實例化了一個Request類,傳遞給urlopen()。
Get方式:
1 import urllib 2 import urllib2 3 4 values={} 5 values['username'] = "[email protected]" 6 values['password']="******" 7 data = urllib.urlencode(values) 8 url = "http://www.xxx.com/login" 9 geturl = url + "?"+data 10 request = urllib2.Request(geturl) 11 response = urllib2.urlopen(request) 12 print response.read()
在上面的代碼中,我們創建了一個字典values,設置了username和password的值,然後通過urlencode函數將字典進行轉碼,命名為data,然後我們把data拼接在了url中,我們會得到這樣的url:http://www.xxx.com/login?username=977610289%40qq.com&password=******。
在實現一個爬蟲的時候,我們要根據需要,選擇post或者get方式進行訪問!不過除了上面那些還不夠,現在網站為了避免爬蟲去訪問會進行一些檢測,如果檢測不通過就不會響應你的請求,為了完全模擬瀏覽器工作,我們往往要設置一些headers屬性,以及防盜鏈:
1 headers = { 'User-Agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' , 2 'Referer':'http://www.zhihu.com/articles' }
3 request = urllib2.Request(url, data, headers)#利用data headers構造Request對象
有些網站可能會檢測ip等,我們可能會用到urllib2的代理,有些網站響應過慢我們可以設置其timeout。在訪問網站的情況下我們可能會遇到一些網站錯誤,我們要在程式中進行處理(一如既往的try... except...得到錯誤信息內容):
1 import urllib2 2 3 req = urllib2.Request('http://www.xxx.com') 4 try: 5 urllib2.urlopen(req) 6 except urllib2.URLError, e: 7 if hasattr(e,"code"): 8 print e.code 9 if hasattr(e,"reason"): 10 print e.reason 11 else: 12 print "OK"
常見的錯誤代碼:400 非法請求 403 禁止訪問 404 未找到資源 500 伺服器內部錯誤 200 訪問成功。
在網頁訪問過程中,不可避免的要用到cookies,我們的程式要模擬瀏覽器的行為,在訪問網頁的時候有時候要帶上特定的cookies,這樣才能成功訪問網頁。關於cookies我們用到了cookielib,cookielib模塊提供可存儲cookie的對象,以便於與urllib2配合使用進行網站訪問,利用其中的CookieJar類捕獲和發送cookie,實現模擬登錄,維持登錄狀態等。
獲取cookie保存到變數:
1 import urllib2 2 import cookielib 3 #聲明一個CookieJar對象實例來保存cookie 4 cookie = cookielib.CookieJar() 5 #利用urllib2庫的HTTPCookieProcessor對象來創建cookie處理器 6 handler=urllib2.HTTPCookieProcessor(cookie) 7 #通過handler來構建opener 8 opener = urllib2.build_opener(handler) 9 #此處的open方法同urllib2的urlopen方法,也可以傳入request 10 response = opener.open('http://www.baidu.com') 11 for item in cookie: 12 print 'Name = '+item.name 13 print 'Value = '+item.value 14 #利用cookie請求訪問另一個網址 15 gradeUrl = 'http://www.baidu.com/xxx/xx' 16 #請求訪問 17 result = opener.open(gradeUrl) 18 print result.read()
上面程式創建了一個帶有cookie的opener,在訪問登錄url的時候,將登錄後的cookie保存下來,然後利用這個cookie來訪問其他的網址。
下麵放一個HttpClient.py,裡面包含了post和get方法,以及getcookies:
1 import cookielib, urllib, urllib2, socket 2 3 class HttpClient: 4 __cookie = cookielib.CookieJar() 5 __req = urllib2.build_opener(urllib2.HTTPCookieProcessor(__cookie)) 6 __req.addheaders = [ 7 ('Accept', 'application/javascript, */*;q=0.8'), 8 ('User-Agent', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)') 9 ] 10 urllib2.install_opener(__req) 11 12 def Get(self, url, refer=None): 13 try: 14 req = urllib2.Request(url) 15 if not (refer is None): 16 req.add_header('Referer', refer) 17 return urllib2.urlopen(req, timeout=120).read() 18 except urllib2.HTTPError, e: 19 return e.read() 20 except socket.timeout, e: 21 return '' 22 except socket.error, e: 23 return '' 24 25 def Post(self, url, data, refer=None): 26 try: 27 req = urllib2.Request(url, urllib.urlencode(data)) 28 if not (refer is None): 29 req.add_header('Referer', refer) 30 return urllib2.urlopen(req, timeout=120).read() 31 except urllib2.HTTPError, e: 32 return e.read() 33 except socket.timeout, e: 34 return '' 35 except socket.error, e: 36 return '' 37 38 def Download(self, url, file): 39 output = open(file, 'wb') 40 output.write(urllib2.urlopen(url).read()) 41 output.close() 42 43 def getCookie(self, key): 44 for c in self.__cookie: 45 if c.name == key: 46 return c.value 47 return '' 48 49 def setCookie(self, key, val, domain): 50 ck = cookielib.Cookie(version=0, name=key, value=val, port=None, port_specified=False, domain=domain, domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False) 51 self.__cookie.set_cookie(ck)