PROXPY / proxy_pool.py
Voxxium's picture
Update proxy_pool.py
b06af5b verified
import random
import threading
import time
from collections import defaultdict
class ProxyEntry:
__slots__ = (
'proxy', 'protocol', 'proxy_url', 'latency',
'proxy_ip', 'verified', 'fail_count', 'total_used',
)
def __init__(self, proxy, protocol, proxy_url,
latency, proxy_ip, verified):
self.proxy = proxy
self.protocol = protocol
self.proxy_url = proxy_url
self.latency = latency
self.proxy_ip = proxy_ip
self.verified = verified
self.fail_count = 0
self.total_used = 0
def to_dict(self):
return {
"proxy": self.proxy,
"protocol": self.protocol,
"proxy_url": self.proxy_url,
"latency": self.latency,
"proxy_ip": self.proxy_ip,
"verified": self.verified,
"total_used": self.total_used,
}
class ProxyPool:
def __init__(self):
self._px = []
self._um = {}
self._lk = threading.Lock()
self._rr = defaultdict(int)
self._lr = 0.0
self._rc = 0
def refresh(self, new_proxies):
with self._lk:
old = dict(self._um)
fresh, um = [], {}
for px in new_proxies:
e = ProxyEntry(
px["proxy"], px["protocol"],
px["proxy_url"], px["latency"],
px.get("proxy_ip", ""),
px.get("verified", False),
)
o = old.get(e.proxy_url)
if o:
e.total_used = o.total_used
e.fail_count = max(0, o.fail_count - 1)
fresh.append(e)
um[e.proxy_url] = e
fresh.sort(key=lambda x: x.latency)
self._px = fresh
self._um = um
self._lr = time.time()
self._rc += 1
@property
def size(self):
return len(self._px)
def _alive(self, protocol=None, verified=False):
r = [p for p in self._px if p.fail_count < 3]
if protocol:
r = [p for p in r if p.protocol == protocol]
if verified:
r = [p for p in r if p.verified]
return r
def get_round_robin(self, protocol=None, verified=False):
with self._lk:
a = self._alive(protocol, verified)
if not a:
return None
k = f"{protocol}_{verified}"
i = self._rr[k] % len(a)
self._rr[k] = i + 1
a[i].total_used += 1
return a[i]
def get_random(self, protocol=None, verified=False):
with self._lk:
a = self._alive(protocol, verified)
if not a:
return None
p = random.choice(a)
p.total_used += 1
return p
def get_fastest(self, protocol=None, verified=False):
with self._lk:
a = self._alive(protocol, verified)
if not a:
return None
a[0].total_used += 1
return a[0]
def get_least_used(self, protocol=None, verified=False):
with self._lk:
a = self._alive(protocol, verified)
if not a:
return None
p = min(a, key=lambda x: x.total_used)
p.total_used += 1
return p
def report_failure(self, url):
with self._lk:
p = self._um.get(url)
if p:
p.fail_count += 1
def report_success(self, url):
with self._lk:
p = self._um.get(url)
if p:
p.fail_count = 0
def get_all(self, protocol=None, verified=False, limit=500):
with self._lk:
return [
p.to_dict()
for p in self._alive(protocol, verified)[:limit]
]
def get_stats(self):
with self._lk:
bp = defaultdict(lambda: {"total": 0, "alive": 0})
for p in self._px:
bp[p.protocol]["total"] += 1
if p.fail_count < 3:
bp[p.protocol]["alive"] += 1
alive = sum(d["alive"] for d in bp.values())
return {
"total": len(self._px),
"alive": alive,
"by_protocol": dict(bp),
"refresh_count": self._rc,
"last_refresh_ago": round(
time.time() - self._lr, 1
) if self._lr else None,
}
def export_json(self):
with self._lk:
return [p.to_dict() for p in self._px]
def import_json(self, data):
proxies = []
for p in data:
proxies.append({
"proxy": p["proxy"],
"protocol": p["protocol"],
"proxy_url": p["proxy_url"],
"latency": p["latency"],
"proxy_ip": p.get("proxy_ip", ""),
"verified": p.get("verified", False),
})
if proxies:
self.refresh(proxies)