自己搭建億級爬蟲IP代理池
做爬蟲抓取時,我們經常會碰到網站針對IP地址封鎖的反爬蟲策略。但只要有大量可用的IP資源,問題自然迎刃而解。
以前嘗試過自己抓取網路上免費代理IP來搭建代理池,可免費IP質量參差不齊,不僅資源少、速度慢,而且失效快,滿足不了快速密集抓取的需求。
收費代理提供的代理資源質量明顯提升,經過多家測試,最終選定使用站大爺作為代理提供平臺。
站大爺代理IP平臺每天能提供大概24萬個不重複的短效高匿代理,每個代理存活期為3分鐘,總IP數有20億,IP數量足夠使用。價格為包天17元,包月475元,還有半年及一年的套餐可供選擇。只要能滿足專案要求,提供優質穩定的服務,這些成本值得付出。
高匿代理才可以真正用來防止爬蟲被封鎖,如果使用普通代理,爬蟲的真實
搭建思路
站大爺提供了大量的代理伺服器資源,主要考慮如何將這些伺服器分配給爬蟲伺服器使用。最初的想法是使用Redis作為代理伺服器資源佇列,一個程式自動獲取站大爺API提供的代理,驗證可用後push到Redis裡,每個程式再從Redis中pop一個代理進行抓取,但這樣的缺點是不太好控制每臺爬蟲伺服器的代理質量,有的代理速度快,有的速度比較慢,影響抓取效率,其次就是需要自行維護一套代理驗證、分配的程式,增加了程式碼量,不便後期維護。
為了解決這些問題,我想到可以使用Squid提供的父代理功能,自動將爬蟲伺服器的請求轉發給代理伺服器。Squid提供了自動輪詢功能,自動驗證並剔除不可用的代理。減少了我們多餘的驗證步驟。
爬蟲軟體只需將代理設定為Squid伺服器即可,不需要每次重新設定為其他的代理伺服器。
這套方案明顯減少了工作量,提高了易用性和可維護性。
實現過程
1. 首先獲取代理平臺提供的代理伺服器資源
o 建議購買短效代理,購買後在後臺獲取API地址並設定IP白名單等引數
2. 將獲取到的代理伺服器寫入squid配置檔案
o 解析網站提供的代理伺服器,按照一定規則寫入/etc/squid/squid.conf
3.
o 寫入配置檔案之後重新載入最新的檔案,不會造成中斷
4. 自動更新,重複1-3
o 由於網站提供的代理存活時間只有2分鐘,所以需要每隔一段時間重新獲取一批新IP
實現上述要求的程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#!/usr/bin/env python # coding: utf-8 # zdy.py ''' Squid+站大爺搭建代理IP池 Author: Nathan Blog: www.xnathan.com Github: github.com/xNathan ''' import os import time import requests # Squid的配置檔案語法 # 將請求轉發到父代理 PEER_CONF = "cache_peer %s parent %s 0 no-query weighted-round-robin weight=1 connect-fail-limit=2 allow-miss max-conn=5\n" def update_conf(proxies): with open('/etc/squid/squid.conf.original', 'r') as F: squid_conf = F.readlines() squid_conf.append('\n# Cache peer config\n') for proxy in proxies: squid_conf.append(PEER_CONF % (proxy[0], proxy[1])) with open('/etc/squid/squid.conf', 'w') as F: F.writelines(squid_conf) def get_proxy(): # 1. 獲取代理IP資源 api_url = 'http://s.zdaye.com/?api=YOUR_API&count=100&fitter=1&px=2' res = requests.get(api_url).content if len(res) == 0: print 'no data' elif 'bad' in res: print 'bad request' else: print 'get all proxies' proxies = [] for line in res.split(): proxies.append(line.strip().split(':')) # 2. 寫入Squid配置檔案 update_conf(proxies) # 3. 重新載入配置檔案 os.system('squid -k reconfigure') print 'done' def main(): start = time.time() while True: # 每60秒獲取一批新IP if time.time() - start >= 60: get_proxy() time.sleep(5) start = time.time() if __name__ == '__main__': main() |
使用方法
1. 按Squid 搭建正向代理伺服器、Squid 配置高匿代理介紹的方法搭建執行Squid高匿伺服器
2. 備份原始配置檔案cp/etc/squid/squid.conf /etc/squid/squid.conf.original,以供軟體使用
3. 在squid伺服器上執行python zdy.py
例項
如果按照上述方法搭建好代理IP池,只需要在爬蟲程式碼中設定設定squid代理伺服器地址和埠(比如139.xxx.xxx.66:3188)。
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/usr/bin/env python # coding: utf-8 ''' 代理IP池例項演示 ''' import requests s = requests.Session() s.proxies.update( {'http': '139.xxx.xxx.66:3188'} ) print s.get('http://httpbin.org/ip') |
每次執行這個程式時,返回的IP都不一樣,而且僅有一個,說明IP代理池已經搭建成功,可以應用在網路爬蟲專案中。
總結
這套解決方案結合了網路上的大量優質代理資源以及Squid伺服器提供的特性,基本解決了網站對於爬蟲IP的封鎖。
成本比較低,而且有比較高的易用性,很方便地能結合到各種爬蟲應用中,只需要增加一個代理地址即可,而由Squid統一管理父代理,不需要在爬蟲程式中進行代理的獲取驗證等等操作,便於維護。
實際使用中還沒有發現什麼特別重大的問題,更多擴充套件性還有待後續繼續研究。
專案地址: https://github.com/xNathan/squid_proxy_pool