|
|
import os |
|
|
import json |
|
|
import random |
|
|
import re |
|
|
import requests |
|
|
import asyncio |
|
|
from fastapi import FastAPI, WebSocket |
|
|
from fastapi.responses import HTMLResponse, Response |
|
|
from threading import Lock |
|
|
import uvicorn |
|
|
from faker import Faker |
|
|
from bs4 import BeautifulSoup |
|
|
|
|
|
app = FastAPI() |
|
|
faker = Faker() |
|
|
valid_proxies = {} |
|
|
invalid_proxies = {} |
|
|
proxies_lock = Lock() |
|
|
|
|
|
def create_headers(): |
|
|
user_agent = faker.user_agent() |
|
|
random_ip = faker.ipv4() |
|
|
return { |
|
|
"User-Agent": user_agent, |
|
|
"X-Forwarded-For": random_ip, |
|
|
"Client-IP": random_ip, |
|
|
"X-Real-IP": random_ip |
|
|
} |
|
|
|
|
|
def is_valid_proxy(proxy: str) -> bool: |
|
|
ip_port_pattern = re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{2,5}$') |
|
|
if ip_port_pattern.match(proxy) is None: |
|
|
return False |
|
|
ip, port = proxy.split(':') |
|
|
if any(char in ip for char in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') or \ |
|
|
any(char in port for char in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): |
|
|
return False |
|
|
return True |
|
|
|
|
|
async def verify_proxy(proxy: str): |
|
|
if not is_valid_proxy(proxy): |
|
|
with proxies_lock: |
|
|
invalid_proxies[proxy] = True |
|
|
return proxy, False |
|
|
|
|
|
test_urls = [ |
|
|
"https://google.com", |
|
|
"https://www.youtube.com/", |
|
|
"http://httpbin.org/ip", |
|
|
"https://instagram.com" |
|
|
] |
|
|
proxy_dict = { |
|
|
"http": f"http://{proxy}", |
|
|
"https": f"http://{proxy}" |
|
|
} |
|
|
headers = create_headers() |
|
|
try: |
|
|
for url in test_urls: |
|
|
try: |
|
|
response = await asyncio.to_thread(requests.get, url, proxies=proxy_dict, headers=headers, timeout=10) |
|
|
response.raise_for_status() |
|
|
except (requests.RequestException, ValueError): |
|
|
with proxies_lock: |
|
|
invalid_proxies[proxy] = True |
|
|
return proxy, False |
|
|
with proxies_lock: |
|
|
valid_proxies[proxy] = True |
|
|
return proxy, True |
|
|
except Exception: |
|
|
with proxies_lock: |
|
|
valid_proxies.pop(proxy, None) |
|
|
invalid_proxies[proxy] = True |
|
|
return proxy, False |
|
|
|
|
|
async def verify_proxies_in_background(): |
|
|
while True: |
|
|
with proxies_lock: |
|
|
proxies_to_verify = list(valid_proxies.keys()) |
|
|
if proxies_to_verify: |
|
|
tasks = [verify_proxy(proxy) for proxy in proxies_to_verify] |
|
|
results = await asyncio.gather(*tasks) |
|
|
for proxy, is_valid in results: |
|
|
if not is_valid: |
|
|
with proxies_lock: |
|
|
valid_proxies.pop(proxy, None) |
|
|
invalid_proxies[proxy] = True |
|
|
await asyncio.sleep(0) |
|
|
|
|
|
async def fetch_proxies_from_sources(): |
|
|
proxy_urls = [ |
|
|
os.getenv("PROXY_API_URL", "http://pubproxy.com/api/proxy?format=txt&level=anonymous,elite&type=http,socks4,socks5&last_check=60&speed=25&limit=1&post=true&user_agent=true&cookies=true&referer=true"), |
|
|
'https://raw.githubusercontent.com/clarketm/proxy-list/master/proxy-list-raw.txt', |
|
|
'https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/http.txt', |
|
|
'https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/socks4.txt', |
|
|
'https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/socks5.txt', |
|
|
'https://raw.githubusercontent.com/ShiftyTR/Proxy-List/master/proxy.txt', |
|
|
'https://raw.githubusercontent.com/sunny9577/proxy-scraper/master/proxies.txt', |
|
|
"https://storage.googleapis.com/river-treat-249913.appspot.com/p.txt", |
|
|
"https://storage.googleapis.com/river-treat-249913.appspot.com/proxy.txt", |
|
|
"https://storage.googleapis.com/river-treat-249913.appspot.com/ultimate.txt", |
|
|
'https://raw.githubusercontent.com/proxylist/proxylist/master/proxy.txt', |
|
|
'https://raw.githubusercontent.com/scrapfly/proxy-list/main/proxies.txt', |
|
|
'https://raw.githubusercontent.com/roosterkid/openproxylist/main/HTTP.txt', |
|
|
'https://raw.githubusercontent.com/roosterkid/openproxylist/main/SOCKS4.txt', |
|
|
'https://raw.githubusercontent.com/roosterkid/openproxylist/main/SOCKS5.txt', |
|
|
'https://raw.githubusercontent.com/roosterkid/openproxylist/main/HTTPS.txt', |
|
|
'https://raw.githubusercontent.com/roosterkid/openproxylist/main/ALL.txt', |
|
|
'https://raw.githubusercontent.com/proxylist/proxylist/master/https.txt', |
|
|
'https://raw.githubusercontent.com/proxylist/proxylist/master/socks4.txt', |
|
|
'https://raw.githubusercontent.com/proxylist/proxylist/master/socks5.txt', |
|
|
'https://raw.githubusercontent.com/proxylist/proxylist/master/http.txt', |
|
|
'https://raw.githubusercontent.com/proxylist/proxylist/master/all.txt', |
|
|
'https://raw.githubusercontent.com/jetlore/proxies/master/proxy-list.txt', |
|
|
'https://raw.githubusercontent.com/hookzof/proxy-list/main/proxy.txt', |
|
|
'https://raw.githubusercontent.com/zzlol123/proxy-list/main/proxies.txt', |
|
|
'https://raw.githubusercontent.com/sqSfg/Proxy-List/master/http.txt', |
|
|
'https://raw.githubusercontent.com/sqSfg/Proxy-List/master/https.txt', |
|
|
'https://raw.githubusercontent.com/sqSfg/Proxy-List/master/socks4.txt', |
|
|
'https://raw.githubusercontent.com/sqSfg/Proxy-List/master/socks5.txt', |
|
|
'https://raw.githubusercontent.com/sqSfg/Proxy-List/master/all.txt', |
|
|
'https://www.proxy-list.download/api/v1/get?type=https', |
|
|
'https://www.proxy-list.download/api/v1/get?type=http', |
|
|
'https://www.proxy-list.download/api/v1/get?type=socks4', |
|
|
'https://www.proxy-list.download/api/v1/get?type=socks5', |
|
|
'https://www.proxy-list.download/api/v1/get?type=all', |
|
|
'https://www.sslproxies.org/', |
|
|
'https://www.us-proxy.org/', |
|
|
'https://free-proxy-list.net/', |
|
|
'https://www.proxy-list.download/', |
|
|
'https://www.proxy-list.org/eng/proxylist.txt', |
|
|
"https://api.proxyscrape.com/v2/?request=displayproxies&protocol=http&timeout=10000&country=all&ssl=all&anonymity=all" |
|
|
] |
|
|
|
|
|
for i in range(2, 52): |
|
|
proxy_urls.append(f'https://free-proxy-list.net/uk-proxy.html?page={i}') |
|
|
|
|
|
proxies = set() |
|
|
|
|
|
for url in proxy_urls: |
|
|
response_text = fetch_response(url) |
|
|
if response_text: |
|
|
if response_text.startswith('{') and response_text.endswith('}'): |
|
|
try: |
|
|
data = json.loads(response_text) |
|
|
if isinstance(data, dict) and 'data' in data: |
|
|
new_proxies = {f"{proxy_data['ip']}:{proxy_data['port']}" for proxy_data in data['data'] if 'ip' in proxy_data and 'port' in proxy_data} |
|
|
proxies.update(new_proxies) |
|
|
except ValueError: |
|
|
pass |
|
|
else: |
|
|
if 'free-proxy-list.net' in url: |
|
|
soup = BeautifulSoup(response_text, 'html.parser') |
|
|
table = soup.find('table', {'id': 'proxylisttable'}) |
|
|
if table: |
|
|
for row in table.find_all('tr')[1:]: |
|
|
try: |
|
|
columns = row.find_all('td') |
|
|
ip = columns[0].text.strip() |
|
|
port = columns[1].text.strip() |
|
|
proxy = f"{ip}:{port}" |
|
|
proxies.add(proxy) |
|
|
except: |
|
|
pass |
|
|
else: |
|
|
lines = response_text.splitlines() |
|
|
new_proxies = {line.strip() for line in lines if line.strip()} |
|
|
proxies.update(new_proxies) |
|
|
|
|
|
with proxies_lock: |
|
|
for proxy in proxies: |
|
|
if is_valid_proxy(proxy): |
|
|
valid_proxies[proxy] = True |
|
|
else: |
|
|
invalid_proxies[proxy] = True |
|
|
return valid_proxies, invalid_proxies |
|
|
|
|
|
@app.on_event("startup") |
|
|
async def on_startup(): |
|
|
global valid_proxies, invalid_proxies |
|
|
valid_proxies, invalid_proxies = await fetch_proxies_from_sources() |
|
|
|
|
|
def fetch_response(url): |
|
|
headers = create_headers() |
|
|
try: |
|
|
response = requests.get(url, headers=headers) |
|
|
response.raise_for_status() |
|
|
return response.text |
|
|
except requests.RequestException: |
|
|
return None |
|
|
|
|
|
|
|
|
@app.get("/") |
|
|
async def root(): |
|
|
html_content = ''' |
|
|
<html> |
|
|
<body> |
|
|
<h1>Proxy List</h1> |
|
|
<p><a href="/valid">Valid Proxies</a></p> |
|
|
<p><a href="/invalid">Invalid Proxies</a></p> |
|
|
</body> |
|
|
</html> |
|
|
''' |
|
|
return HTMLResponse(content=html_content, status_code=200) |
|
|
|
|
|
@app.get("/valid") |
|
|
async def valid_proxies_endpoint(): |
|
|
with proxies_lock: |
|
|
valid_proxies_list = list(valid_proxies.keys()) |
|
|
if len(valid_proxies_list) > 10: |
|
|
valid_proxies_list = random.sample(valid_proxies_list, 10) |
|
|
response_content = "\n".join(valid_proxies_list) |
|
|
return Response(content=response_content, media_type='text/plain') |
|
|
|
|
|
@app.get("/invalid") |
|
|
async def invalid_proxies_endpoint(): |
|
|
with proxies_lock: |
|
|
invalid_proxies_list = list(invalid_proxies.keys()) |
|
|
if len(invalid_proxies_list) > 10: |
|
|
invalid_proxies_list = random.sample(invalid_proxies_list, 10) |
|
|
response_content = "\n".join(invalid_proxies_list) |
|
|
return Response(content=response_content, media_type='text/plain') |
|
|
|
|
|
@app.websocket("/ws") |
|
|
async def websocket_endpoint(websocket: WebSocket): |
|
|
await websocket.accept() |
|
|
while True: |
|
|
with proxies_lock: |
|
|
proxies_list = list(valid_proxies.keys()) |
|
|
await websocket.send_text("\n".join(proxies_list)) |
|
|
await asyncio.sleep(0) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
uvicorn.run(app, host="0.0.0.0", port=7860) |