opener是 urllib2.OpenerDirector 的實例,其中urlopen是模塊默認構建的opener。 可是基本的urlopen()方法不支持代理、cookie等其餘的HTTP/HTTPS高級功能。若是要支持這些功能,能夠使用相關的 Handler處理器來建立特定功能的處理器對象,而後經過 urllib2.build_opener()方法使用這些處理器對象,建立自定義opener對象,最後 使用自定義的opener對象,調用open()方法發送請求。 html
自定義一個簡單的opener()web
-*- coding: utf-8 -*- import urllib2 # 構建一個HTTPHandler 處理器對象,支持處理HTTP請求 http_handler = urllib2.HTTPHandler() # 構建一個HTTPHandler 處理器對象,支持處理HTTPS請求 # http_handler = urllib2.HTTPSHandler() # 調用urllib2.build_opener()方法,建立支持處理HTTP請求的opener對象 opener = urllib2.build_opener(http_handler) # 構建 Request請求 request = urllib2.Request("http://www.baidu.com/") # 調用自定義opener對象的open()方法,發送request請求 response = opener.open(request) # 獲取服務器響應內容 print response.read() # 開啓Debug Log程序在執行的時候,會把收包和發包的報頭在屏幕上自動打印出來 # 構建一個HTTPHandler 處理器對象,支持處理HTTP請求,同時開啓Debug Log,debuglevel 值默認 0 # http_handler = urllib2.HTTPHandler(debuglevel=1) # 構建一個HTTPHSandler 處理器對象,支持處理HTTPS請求,同時開啓Debug Log,debuglevel 值默認 0 # https_handler = urllib2.HTTPSHandler(debuglevel=1)
使用代理IP,這也是爬蟲/反爬蟲的有效方式,不少網站會檢測某一段時間某個IP的訪問次數,若是訪問頻率太高,就有可能被禁止訪問。這時能夠設置一些代理服務器,每隔一段時間換一個代理,就算IP被禁止,依然能夠換個IP繼續爬取。瀏覽器
在urllib2中能夠經過ProxyHandler來設置使用代理服務器:服務器
# -*- coding: utf-8 -*- import urllib2 # 構建了兩個代理Handler,一個有代理IP,一個沒有代理IP httpproxy_handler = urllib2.ProxyHandler({"http" : "124.88.67.81:80"}) nullproxy_handler = urllib2.ProxyHandler({}) proxySwitch = True #定義一個代理開關 # 經過 urllib2.build_opener()方法使用這些代理Handler對象,建立自定義opener對象 # 根據代理開關是否打開,使用不一樣的代理模式 if proxySwitch: opener = urllib2.build_opener(httpproxy_handler) else: opener = urllib2.build_opener(nullproxy_handler) request = urllib2.Request("http://www.baidu.com/") # 只有使用opener.open()方法發送請求才使用自定義的代理,而urlopen()則不使用自定義代理。 response = opener.open(request) # 將opener應用到全局,以後不論是opener.open()仍是urlopen() 發送請求,都將使用自定義代理。 # urllib2.install_opener(opener) # response = urlopen(request) print response.read()
免費的開放代理很容易獲取,有很多這樣的網站,能夠多收集一些代理IP,這樣能夠像隨機獲取User-Agent同樣,隨機選擇一個代理去訪問網站:cookie
# -*- coding: utf-8 -*- import urllib2 import random proxy_list = [ {"http" : "124.88.67.81:80"}, {"http" : "124.88.67.81:80"}, {"http" : "124.88.67.81:80"}, {"http" : "124.88.67.81:80"}, {"http" : "124.88.67.81:80"} ] # 隨機選擇一個代理 proxy = random.choice(proxy_list) # 使用選擇的代理構建代理處理器對象 httpproxy_handler = urllib2.ProxyHandler(proxy) opener = urllib2.build_opener(httpproxy_handler) request = urllib2.Request("http://www.baidu.com/") response = opener.open(request) print response.read()
免費代理不穩定,若是要求高就購買私密代理,購買私密代理後會獲得一個帳戶和密碼做爲認證,具體使用以下:網絡
# -*- coding:utf-8 -*- import urllib2 # 私密代理受權的帳戶 user = "xxxx" # 私密代理受權的密碼 passwd = "****" # 受權的代理帳戶密碼拼接 authproxy_handler = urllib2.ProxyHandler({"http" : user+":"+passwd+"@114.215.104.49:16816"}) # 構建一個自定義的opener opener = urllib2.build_opener(authproxy_handler) # 構建請求 request = urllib2.Request("http://www.baidu.com/") # 獲取響應 response = opener.open(request) # 打印內容 print response.read()
爲避免帳戶密碼泄露能夠將其寫入環境變量中。app
# -*- coding: utf-8 -*- from __future__ import unicode_literals import urllib import urllib2 # 用戶名 user = "xxxx" # 密碼 passwd = "****" # Web服務器 IP webserver = "http://192.168.12.33" # 構建一個密碼管理對象,用來保存須要處理的用戶名和密碼 passwdmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() # 添加帳戶信息,第一個參數realm是與遠程服務器相關的域信息,通常沒人管它都是寫None,後面三個參數分別是 Web服務器、用戶名、密碼 passwdmgr.add_password(None, webserver, user, passwd) # 構建一個HTTP基礎用戶名/密碼驗證的HTTPBasicAuthHandler處理器對象,參數是建立的密碼管理對象 httpauth_handler = urllib2.HTTPBasicAuthHandler(passwdmgr) # 經過 build_opener()方法使用這些代理Handler對象,建立自定義opener對象,參數包括構建的 proxy_handler opener = urllib2.build_opener(httpauth_handler) # 能夠選擇經過install_opener()方法定義opener爲全局opener urllib2.install_opener(opener) # 構建 Request對象 request = urllib2.Request("http://192.168.199.107") # 定義opener爲全局opener後,可直接使用urlopen()發送請求 response = urllib2.urlopen(request) # 打印響應內容 print response.read()
這種網站比較少,遇到時咱們可使用requests庫來爬取會方便不少,這種方法過於繁瑣。dom
Cookie 是指某些網站服務器爲了辨別用戶身份和進行Session跟蹤,而儲存在用戶瀏覽器上的文本文件,Cookie能夠保持登陸信息到用戶下次與服務器的會話。網站
Cookies在爬蟲方面最典型的應用是斷定註冊用戶是否已經登陸網站,用戶可能會獲得提示,是否在下一次進入此網站時保留用戶信息以便簡化登陸手續。ui
經過抓包獲取一個有登陸信息的Cookie來模擬登錄:
# -*- coding: utf-8 -*- import urllib2 # 構建一個已經登陸過的用戶的headers信息 headers = { "Host":"www.renren.com", "Connection":"keep-alive", "Upgrade-Insecure-Requests":"1", "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36", "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language":"zh-CN,zh;q=0.8,en;q=0.6", # 這個Cookie是保存了密碼無需重複登陸的用戶的Cookie,經過抓包獲取(這裏只是一部分) "Cookie": "anonymid=efrna3fysufnwv; depovince=GW; _r01_=1; " } # 經過headers裏的報頭信息(主要是Cookie信息),構建Request對象 urllib2.Request("http://www.renren.com/", headers = headers) # 直接訪問renren主頁,服務器會根據headers報頭信息(主要是Cookie信息),判斷這是一個已經登陸的用戶,並返回相應的頁面 response = urllib2.urlopen(request) # 打印響應內容 print response.read()
# -*- coding: utf-8 -*- import urllib2 import cookielib # 構建一個CookieJar對象實例來保存cookie cookiejar = cookielib.CookieJar() # 使用HTTPCookieProcessor()來建立cookie處理器對象,參數爲CookieJar()對象 handler=urllib2.HTTPCookieProcessor(cookiejar) # 經過 build_opener() 來構建opener opener = urllib2.build_opener(handler) # 4. 以get方法訪問頁面,訪問以後會自動保存cookie到cookiejar中 opener.open("http://www.baidu.com")
# -*- coding: utf-8 -*- import cookielib import urllib2 # 保存cookie的本地磁盤文件名 filename = 'cookie.txt' # 聲明一個MozillaCookieJar(有save實現)對象實例來保存cookie,以後寫入文件 cookiejar = cookielib.MozillaCookieJar(filename) # 使用HTTPCookieProcessor()來建立cookie處理器對象,參數爲CookieJar()對象 handler = urllib2.HTTPCookieProcessor(cookiejar) # 經過 build_opener() 來構建opener opener = urllib2.build_opener(handler) # 建立一個請求,原理同urllib2的urlopen response = opener.open("http://www.baidu.com") # 保存cookie到本地文件 cookiejar.save()
# -*- coding: utf-8 -*- import cookielib import urllib2 # 建立MozillaCookieJar(有load實現)實例對象 cookiejar = cookielib.MozillaCookieJar() # 從文件中讀取cookie內容到變量 cookie.load('cookie.txt') # 使用HTTPCookieProcessor()來建立cookie處理器對象,參數爲CookieJar()對象 handler = urllib2.HTTPCookieProcessor(cookiejar) # 經過 build_opener() 來構建opener opener = urllib2.build_opener(handler) response = opener.open("http://www.baidu.com")
在咱們用urlopen或opener.open方法發出一個請求時,若是urlopen或opener.open不能處理這個response,就產生錯誤。主要有URLError和HTTPError。
URLError 產生的緣由主要有:沒有網絡鏈接、服務器鏈接失敗、找不到指定的服務器。
HTTPError是URLError的子類,咱們發出一個請求時,服務器上都會對應一個response應答對象,其中它包含一個數字"響應狀態碼"。若是urlopen或opener.open不能處理的,會產生一個HTTPError,對應相應的狀態碼,HTTP狀態碼錶示HTTP協議所返回的響應的狀態。
異常處理程序:
# -*- coding: utf-8 -*- # 一、URLError import urllib2 # 訪問一個不存在的域名 requset = urllib2.Request('http://www.ajkfhafwjqh.com') try: urllib2.urlopen(request, timeout=5) except urllib2.URLError, err: print err # 二、HTTPError import urllib2 requset = urllib2.Request('http://blog.baidu.com/zhihu') try: urllib2.urlopen(requset) except urllib2.HTTPError, err: # 打印狀態碼 print err.code print err #三、因爲HTTPError的父類是URLError,因此父類的異常應當寫到子類異常的後面,因此上述的代碼能夠這麼改寫: import urllib2 requset = urllib2.Request('http://blog.baidu.com/zhihu') try: urllib2.urlopen(requset) except urllib2.HTTPError, err: print err.code except urllib2.URLError, err: print err else: print "OK"