在之前的文章中我們帶入了 opener 方法,接下來我們看一下 opener 應用中的 ProxyHandler 處理器(代理設置)。
使用代理IP,這是爬蟲/反爬蟲的第二大招,通常也是最好用的。
很多網站會檢測某一段時間某個IP的訪問次數(通過流量統計,系統日志等),如果訪問次數多的不像正常人,它會禁止這個IP的訪問。
所以我們可以設置一些代理服務器,每隔一段時間換一個代理,就算IP被禁止,依然可以換個IP繼續爬取。
urllib.request 中通過ProxyHandler來設置使用代理服務器,下面代碼說明如何使用自定義 opener 來使用代理:
1 import urllib.request 2 3 # 構建了兩個代理Handler,一個有代理IP,一個沒有代理IP 4 httpproxy_handler = urllib.request.ProxyHandler({"https": "27.191.234.69:9999"}) 5 nullproxy_handler = urllib.request.ProxyHandler({}) 6 7 # 定義一個代理開關 8 proxySwitch = True 9 10 # 通過 urllib.request.build_opener()方法使用這些代理Handler對象,創建自定義opener對象 11 # 根據代理開關是否打開,使用不同的代理模式 12 if proxySwitch: 13 opener = urllib.request.build_opener(httpproxy_handler) 14 else: 15 opener = urllib.request.build_opener(nullproxy_handler) 16 17 request = urllib.request.Request("http://www.baidu.com/") 18 19 # 1. 如果這么寫,只有使用opener.open()方法發送請求才使用自定義的代理,而urlopen()則不使用自定義代理。 20 response = opener.open(request) 21 22 # 2. 如果這么寫,就是將opener應用到全局,之后所有的,不管是opener.open()還是urlopen() 發送請求,都將使用自定義代理。 23 # urllib.request.install_opener(opener) 24 # response = urllib.request.urlopen(request) 25 26 # 獲取服務器響應內容 27 html = response.read().decode("utf-8") 28 29 # 打印字符串 30 print(html)
最終結果如下:
在上面的代碼第 4 行,我們使用了一個免費的代理 IP,國內有很多免費的代理 IP 地址,如下:
但是上面的免費代理只支持短期的,就是說在我們在短期爬取信息或者自己做測試可以去上面找可以使用的,但是如果要是長期的話我們需要自己購買代理 IP 比較穩妥。
為了避免我們的代理 IP 被封后爬取失敗,我們可以使用多個代理 Ip,然后不定時切換就可以了,如下:
1 import urllib.request 2 import random 3 4 # 代理列表 5 proxy_list = [ 6 {"http": "27.191.234.69:9999"}, 7 {"http": "27.191.234.69:9999"}, 8 {"http": "27.191.234.69:9999"}, 9 {"http": "27.191.234.69:9999"}, 10 ] 11 # 隨機選擇一個代理 12 proxy = random.choice(proxy_list) 13 # 使用選擇的代理構建代理處理器對象 14 httpproxy_handler = urllib.request.ProxyHandler(proxy) 15 16 # 通過 urllib.request.build_opener()方法使用這些代理Handler對象,創建自定義opener對象 17 opener = urllib.request.build_opener(httpproxy_handler) 18 19 request = urllib.request.Request("http://www.baidu.com/") 20 response = opener.open(request) 21 html = response.read().decode("utf-8") 22 print(html)
接下來我們看一下自己購買的私密 IP 該如何使用代理。
1 import urllib.request 2 3 # 私密代理授權的賬戶 4 user = "user" 5 # 私密代理授權的密碼 6 passwd = "passwd" 7 # 私密代理 IP 8 proxyserver = "62.151.164.138:12816" 9 10 # 1. 構建一個密碼管理對象,用來保存需要處理的用戶名和密碼 11 passwdmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() 12 13 # 2. 添加賬戶信息,第一個參數realm是與遠程服務器相關的域信息,一般沒人管它都是寫None,后面三個參數分別是 代理服務器、用戶名、密碼 14 passwdmgr.add_password(None, proxyserver, user, passwd) 15 16 # 3. 構建一個代理基礎用戶名/密碼驗證的 ProxyBasicAuthHandler 處理器對象,參數是創建的密碼管理對象 17 # 注意,這里不再使用普通 ProxyHandler 類了 18 proxyauth_handler = urllib.request.ProxyBasicAuthHandler(passwdmgr) 19 20 # 4. 通過 build_opener()方法使用這些代理 Handler 對象,創建自定義 opener 對象,參數包括構建的 proxy_handler 和 proxyauth_handler 21 opener = urllib.request.build_opener(proxyauth_handler) 22 23 # 5. 構造Request 請求 24 request = urllib.request.Request("http://www.baidu.com/") 25 26 # 6. 使用自定義opener發送請求 27 response = opener.open(request) 28 29 # 7. 打印響應內容 30 html = response.read().decode("utf-8") 31 print(html)
免費開放代理一般會有很多人都在使用,而且代理有壽命短,速度慢,匿名度不高,HTTP/HTTPS支持不穩定等缺點(免費沒好貨)。
專業爬蟲工程師或爬蟲公司會使用高品質的私密代理,這些代理通常需要找專門的代理供應商購買,再通過用戶名/密碼授權使用(舍不得孩子套不到狼)。