| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- import httpx
- import time
- import json
- import uuid
- import logging
- import websockets
- from typing import Optional, List
- from websockets import WebSocketCommonProtocol
- logging.basicConfig(level=logging.INFO)
- BASE_URL = "http://192.168.31.194"
- PORT_LIST = [
- ["58001", "59001"],
- ["58002", "59002"],
- ["58003", "59003"],
- ["58004", "59004"],
- ["58005", "59005"],
- ["58006", "59006"],
- ["58007", "59007"],
- ["58008", "59008"],
- ["58009", "59009"],
- ["58010", "59010"],
- ]
- TEST_URL = "https://httpbin.org/ip"
- class ClashProxyManager:
- def __init__(self, base_url, base_port, test_url):
- self.key_group = 0
- self.base_url = base_url
- self.base_port = base_port
- self.proxy_keyword = [
- ['sg', 'SG', '新加坡', '马来西亚'],
- ['jp', '日本'],
- ]
- self.test_url = test_url
- self.all_proxies = []
- self.selected_proxies = []
- def get_all_proxies(self, clash_tool_url: str) -> List[str]:
- url = f"{clash_tool_url}/api/proxies"
- try:
- response = httpx.get(url)
- response.raise_for_status()
- proxies = response.json()
- logging.info("Available proxies:")
- # 输出读取的所有代理信息
- # for proxy_name, proxy_info in proxies['proxies'].items():
- # logging.info(f"Name: {proxy_name}, Type: {proxy_info.get('type', 'Unknown')}")
- return list(proxies['proxies'].keys())
- except Exception as e:
- logging.error(f"Failed to get proxies: {e}")
- return []
- def filter_proxy(self):
- for keyword in self.proxy_keyword[self.key_group]:
- for item in self.all_proxies:
- if keyword.lower() in item.lower():
- self.selected_proxies.append(item)
- def switch_proxy(self, proxy_name: str, url_and_port: str) -> None:
- logging.info("switch proxy")
- url = f"{url_and_port}/api/proxies/GLOBAL"
- data = {"name": proxy_name}
- try:
- response = httpx.put(url, json=data)
- if response.status_code == 204:
- logging.info(f"Switched to proxy: {proxy_name}")
- else:
- logging.error(f"Failed to switch proxy: {response.status_code} - {proxy_name}")
- except Exception as e:
- logging.error(f"Failed to switch proxy: {e}")
- def update_configs(self):
- for base_port in self.base_port:
- url_and_port = self.base_url + ":" + base_port[0]
- key = "/api/configs"
- url = url_and_port + key
- headers = {
- "accept": "application/json, text/plain, */*",
- "accept-encoding": "gzip, deflate, br, zstd",
- "accept-language": "zh-CN,zh",
- "connection": "keep-alive",
- "content-type": "application/json",
- "origin": url_and_port,
- "referer": url_and_port,
- "sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132", "Brave";v="132"',
- "sec-ch-ua-mobile": "?0",
- "sec-ch-ua-platform": '"macOS"',
- "sec-fetch-dest": "empty",
- "sec-fetch-mode": "cors",
- "sec-fetch-site": "same-origin",
- "sec-gpc": "1",
- "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
- }
- # 请求体数据
- data = {"mode": "Global"} # 替换为实际的请求数据
- # 使用 httpx 发送 PATCH 请求
- try:
- with httpx.Client() as client:
- response = client.patch(url, headers=headers, json=data)
- if response.status_code == 204:
- print(f"{url} OK")
- else:
- print("响应内容:", response.text)
- except httpx.RequestError as exc:
- print(f"请求失败: {exc}")
- def check_proxy(self, proxy_url):
- # proxy_url: 代理地址, 没有密码
- # 测试目标地址:
- try:
- # 使用代理发送请求
- response = httpx.get(
- TEST_URL,
- proxies={"http": proxy_url, "https": proxy_url},
- timeout=5
- )
- response.raise_for_status() # 检查请求是否成功
- # 如果请求成功,返回 True
- return True
- except Exception:
- # 如果发生任何异常,返回 False
- return False
- def main(self) -> None:
- # 设置全局代理
- self.update_configs()
- # 读取所有代理
- if not self.all_proxies:
- for port_list in self.base_port:
- base_url = self.base_url + ":" + port_list[0]
- clash_tool_url = f"{base_url}"
- proxies = self.get_all_proxies(clash_tool_url)
- if proxies:
- self.all_proxies = proxies
- break
- if not self.all_proxies:
- logging.error("Failed to get all proxies")
- return
- # 通过关键词过滤出需要的代理
- self.filter_proxy()
- if not self.selected_proxies:
- logging.error("Failed to filter proxies")
- return
- # 遍历所有的线路api, 切换不重复代理
- # 切换后, 检测代理, 如果检测返回失败, 再次切换
- used_proxy = []
- for base_port in self.base_port:
- url_and_port = self.base_url + ":" + base_port[0]
- proxy_url = self.base_url + ":" + base_port[1]
- for select_proxy in self.selected_proxies:
- if select_proxy in used_proxy:
- continue
- # 尝试切换代理并检测
- self.switch_proxy(select_proxy, url_and_port)
- if self.check_proxy(proxy_url):
- print(f"代理 {select_proxy} 切换成功,检测通过!")
- used_proxy.append(select_proxy) # 标记为已使用
- break # 成功后退出当前代理的重试循环
- else:
- print(f"{url_and_port} 切换 {select_proxy} 检测失败")
- time.sleep(1) # 等待一段时间后重试
- # 如果当前代理成功,直接进入下一个 base_port 的处理
- break
- if __name__ == "__main__":
- manager = ClashProxyManager(BASE_URL, PORT_LIST, TEST_URL)
- manager.main()
|