6 回复
干什么用的啊
帖子标题:Python中如何简单维护IP代理池(开发中)
搞代理池,核心就三件事:获取、验证、存储。一个简单的维护流程可以这样设计:
- 获取代理:从免费/付费API或网页抓取一批IP。
- 验证代理:异步检查这批IP是否有效、匿名性、延迟。
- 存储有效代理:把能用的IP存起来(比如用Redis,方便设置过期时间)。
- 定期更新:定时跑上面的流程,剔除失效的,补充新的。
下面是一个最基础的、可运行的示例,用了 aiohttp 做异步验证,Redis 做存储。你先感受下这个骨架:
import asyncio
import aiohttp
import redis
from typing import List
class SimpleProxyPool:
def __init__(self, redis_host='localhost', redis_port=6379):
self.redis_client = redis.Redis(host=redis_host, port=redis_port, decode_responses=True)
self.test_url = "http://httpbin.org/ip" # 用来验证代理的地址
self.proxy_key = "valid_proxies"
async def check_proxy(self, session: aiohttp.ClientSession, proxy: str) -> bool:
"""检查单个代理是否有效"""
try:
async with session.get(self.test_url, proxy=f"http://{proxy}", timeout=5) as resp:
if resp.status == 200:
# 检查返回的IP是否确实是代理IP(简易匿名性检查)
returned_ip = (await resp.json()).get("origin")
if returned_ip and returned_ip in proxy:
return True
except Exception:
pass
return False
async def validate_proxies(self, proxies: List[str]):
"""批量验证代理列表"""
async with aiohttp.ClientSession() as session:
tasks = [self.check_proxy(session, p) for p in proxies]
results = await asyncio.gather(*tasks, return_exceptions=True)
valid_proxies = [p for p, is_valid in zip(proxies, results) if is_valid is True]
# 存入Redis,设置10分钟过期
if valid_proxies:
self.redis_client.delete(self.proxy_key)
self.redis_client.sadd(self.proxy_key, *valid_proxies)
self.redis_client.expire(self.proxy_key, 600)
print(f"验证完成,有效代理数:{len(valid_proxies)}")
def get_random_proxy(self) -> str:
"""从池中随机取一个代理"""
return self.redis_client.srandmember(self.proxy_key)
# 使用示例
async def main():
pool = SimpleProxyPool()
# 假设这是你从某个源抓到的代理列表
fresh_proxies = ["123.45.67.89:8080", "111.222.333.444:9999", "无效的代理:12345"]
await pool.validate_proxies(fresh_proxies)
# 使用时随机取一个
proxy = pool.get_random_proxy()
if proxy:
print(f"使用的代理:{proxy}")
else:
print("池子里没代理了,得去抓新的了")
if __name__ == "__main__":
asyncio.run(main())
总结一下:先跑通这个基础循环(抓取->验证->存储),再考虑加代理源、评分机制、过期策略这些。
维护可用的 IP 代理池, 为爬虫服务
谢谢。已经在服务器上全部加入 denylist 了。
真的皮; 不过动态的数据,也没法针对
6666

