111 lines
3.7 KiB
Python
111 lines
3.7 KiB
Python
"""
|
|
Proxy rotation checker for V2EX/Discourse account validation.
|
|
Usage: python proxy_checker.py <accounts_file>
|
|
"""
|
|
import requests
|
|
import json
|
|
import itertools
|
|
import time
|
|
import sys
|
|
import os
|
|
|
|
# === CONFIG ===
|
|
PROXY_SOURCES = [
|
|
'https://proxylist.geonode.com/api/proxy-list?limit=20&protocols=socks5',
|
|
'https://api.proxyscrape.com/v4/free-proxy-list/get?request=display_proxies&protocol=socks5&timeout=10000&limit=20',
|
|
'https://openproxy.space/list/socks5',
|
|
]
|
|
|
|
def fetch_proxies():
|
|
"""Get fresh SOCKS5 proxies from multiple sources."""
|
|
proxies = []
|
|
for url in PROXY_SOURCES:
|
|
try:
|
|
r = requests.get(url, timeout=10)
|
|
if 'geonode' in url:
|
|
data = r.json()
|
|
for p in data.get('data', []):
|
|
proxies.append(f"socks5://{p['ip']}:{p['port']}")
|
|
elif 'openproxy' in url:
|
|
for line in r.text.strip().split('\n')[:20]:
|
|
if ':' in line and not line.startswith('#'):
|
|
proxies.append(f"socks5://{line.strip()}")
|
|
else:
|
|
for line in r.text.strip().split('\n'):
|
|
if line.strip():
|
|
proxies.append(f"socks5://{line.strip()}")
|
|
except Exception as e:
|
|
print(f" [!] Proxy source failed: {url[:50]}... {e}")
|
|
|
|
return list(set(proxies))
|
|
|
|
def test_proxies(proxies, test_url, max_test=20):
|
|
"""Filter proxies that can reach the target."""
|
|
working = []
|
|
for proxy_url in proxies[:max_test]:
|
|
try:
|
|
proxy_dict = {'http': proxy_url, 'https': proxy_url}
|
|
r = requests.get(test_url, proxies=proxy_dict, timeout=10,
|
|
headers={'User-Agent': 'Mozilla/5.0'})
|
|
if r.status_code == 200 and 'Restricted' not in r.text:
|
|
working.append(proxy_url)
|
|
print(f" [+] {proxy_url}")
|
|
except:
|
|
pass
|
|
return working
|
|
|
|
def parse_accounts(filepath):
|
|
"""Parse user:pass file. Returns list of (host, username, password)."""
|
|
entries = []
|
|
with open(filepath, encoding='utf-8') as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
parts = line.split(':')
|
|
if len(parts) >= 3:
|
|
pw = parts[-1]
|
|
user = parts[-2]
|
|
host = ':'.join(parts[:-2])
|
|
entries.append((host, user, pw))
|
|
|
|
# Dedup
|
|
seen = set()
|
|
unique = []
|
|
for h, u, p in entries:
|
|
key = (u.lower().strip(), p)
|
|
if key not in seen:
|
|
seen.add(key)
|
|
unique.append((h, u, p))
|
|
|
|
return unique
|
|
|
|
if __name__ == '__main__':
|
|
if len(sys.argv) < 2:
|
|
print("Usage: python proxy_checker.py <accounts_file>")
|
|
sys.exit(1)
|
|
|
|
filepath = sys.argv[1]
|
|
print(f"[*] Parsing {filepath}...")
|
|
accounts = parse_accounts(filepath)
|
|
print(f"[*] {len(accounts)} unique accounts")
|
|
|
|
print("[*] Fetching proxies...")
|
|
proxies = fetch_proxies()
|
|
print(f"[*] {len(proxies)} proxies fetched")
|
|
|
|
print("[*] Testing proxies against target...")
|
|
working = test_proxies(proxies, 'https://www.v2ex.com/signin')
|
|
print(f"[*] {len(working)} working proxies")
|
|
|
|
# Save
|
|
out = os.path.splitext(filepath)[0] + '_parsed.json'
|
|
with open(out, 'w') as f:
|
|
json.dump([{"host": h, "user": u, "pass": p} for h, u, p in accounts], f, indent=2, ensure_ascii=False)
|
|
print(f"[*] Saved parsed accounts to {out}")
|
|
|
|
proxy_out = os.path.join(os.path.dirname(filepath), 'working_socks5.txt')
|
|
with open(proxy_out, 'w') as f:
|
|
f.write('\n'.join(working))
|
|
print(f"[*] Saved working proxies to {proxy_out}")
|