做爬蟲時,遇到訪問太頻繁IP被封是難以避免的,而本地單個IP是不足以進行大規模爬取,並且自己並不想購買付費代理,在這裏構建一個IP代理池是非常有必要的。
代理池主要由5部分組成:ProxyGeter(代理獲取模塊)、RedisClient(代理管理模塊,負責存儲、刪除、取出等基本操作)、Texter(代理可用性測試模塊)和Web_Api(用戶獲取模塊)。
ProxyGeter
從幾個代理網站爬取最新的代理,並把代理存儲到redis數據庫中
RedisClient
主要實現ip的刪、減、增等基本操作,
採用reids的幾方面原因如下:
- redis的hash數據結構可以爲IP的有效性(根據可用性分爲0-100)進行評分;
- redis提供的key-value更方便地儲存IP;
- 對於IP的存儲、提取、刪除、查詢數量等功能會更加地快捷;
Texter
模塊的主要目的是檢測ip的可用性。提前設置好需要檢測的網站站點,然後隨機取出數據庫中的代理,用獲取到的ip來訪問目標站點:
- 若訪問無效,首先降低ip的分數等級(減10),其次做判斷:若該ip的分數等級低於10分直接從reids數據庫中刪除;
- 若訪問有效,首先增加ip的分數等級(加10),其次更新reids中該ip的分數等級;
Web_Api
爲了讓用戶獲取可用性ip更加方便一點,這裏利用flask框架做了一個API,這個接口連接着redis數據庫;
當打開這個api開關時,直接從redis數據庫中隨機獲取一個分數等級高的ip,用戶可以通過訪問這個接口(提供的url)就可以獲取相應的IP代理。
這四個模塊時彼此獨立的(例如,當檢測一個ip不可用時,需要調用RedisClient來從數據庫中刪除這個ip),因此需要引入一個新的模塊:Schedule來進行協調。
代理池的運作關係如下圖:
代碼實現部分
在構建ip代理池過程中,如果使用redis數據庫和flask框架,則需要提前完成相關配置。
部分代碼:
class Tester(object):
def __init__(self):
self.redis =Redisclient()
async def text_single_proxy(self,proxy):
'''
測試單個代理的可用性;
:param proxy: 單個代理;
:return:
'''
conn = aiohttp.TCPConnector(verify_ssl=False)
async with aiohttp.ClientSession(connector=conn) as session:
try:
if isinstance(proxy,bytes):
proxy =proxy.decode('utf-8')
real_proxy = 'http://'+proxy
async with session.get(TEXT_URL,proxy = real_proxy,timeout = 15) as response:
if response.status in VAILD_SATTUS_CODES:
self.redis.max(proxy)
print('')
print('代理可用',proxy)
else:
self.redis.decrease_proxy(proxy)
print('請求響應碼不合法',proxy)
except (TimeoutError,AttributeError):
self.redis.decrease_proxy(proxy)
print('代理請求失敗')
def run(self):
'''
調用主函數;
:return:
'''
print('測試器開始運行')
try:
proxies = self.redis.get_all_prpxy()
loop =asyncio.get_event_loop()
#批量測試
for i in range(0,len(proxies),BATCH_TEXT_SIZE):
test_proxies = proxies[i:i+BATCH_TEXT_SIZE]
tasks = [self.text_single_proxy(proxy) for proxy in test_proxies]
loop.run_until_complete(asyncio.wait(tasks))
time.sleep(5)
except Exception as e:
print('測試器發生錯誤',e.args)
ip代理池實現效果
-
獲取、測試代理:
-
Flask_api接口獲取代理:
以上是ip代理池的整個搭建過程,但是與映射於一句話 最便宜的也就是最貴的一樣,源於免費,會造成大量用戶使用,並且ip的質量堪憂,遠不如付費ip。關於全部源碼的獲取方式:關注微信公衆號:Z先生點記,後臺回覆關鍵詞:ip代理0907 即可。