switch_random_proxy_web3.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. # -*- coding: utf-8 -*-
  2. '''
  3. 切换到随机代理
  4. '''
  5. import random
  6. from urllib.parse import quote
  7. import httpx
  8. import time
  9. import subprocess
  10. from typing import List
  11. BASE_URL = "http://192.168.31.194"
  12. PORT_LIST = ['58001', '58002', '58003', '58004', '58005', '58006', '58007', '58008', '58009', '58010']
  13. PROXY_GROUP = []
  14. # PROXY_GROUP = ['香港', 'HK', '新加坡', 'SG', '台湾', 'TW', '日本', 'JP', '韩国', '澳门']
  15. GROUP = 1
  16. class ClashProxyManager:
  17. def __init__(self, base_url, base_port):
  18. self.key_group = 0
  19. self.base_url = base_url
  20. self.base_port = base_port
  21. self.all_proxies = []
  22. self.used_proxy = []
  23. def get_all_proxies(self, clash_tool_url: str) -> List[str]:
  24. # 连接其中一个代理服务器, 获取所有代理节点, 因为每个代理服务器的所有节点都是一样的, 所以获取一个就行了
  25. url = f"{clash_tool_url}/api/proxies"
  26. try:
  27. response = httpx.get(url)
  28. response.raise_for_status()
  29. proxies = response.json()
  30. # 输出读取的所有代理信息
  31. # for proxy_name, proxy_info in proxies['proxies'].items():
  32. # logging.info(f"Name: {proxy_name}, Type: {proxy_info.get('type', 'Unknown')}")
  33. proxy_list = list(proxies['proxies'].keys())
  34. result_data = []
  35. if GROUP == 1:
  36. for filtered in proxy_list:
  37. for group in PROXY_GROUP:
  38. if group.lower() in filtered.lower() and filtered not in {'REJECT', 'GLOBAL', 'DIRECT'}:
  39. result_data.append(filtered)
  40. elif GROUP == 2:
  41. for filtered in proxy_list:
  42. if all(group.lower() not in filtered.lower() for group in PROXY_GROUP) and filtered not in {
  43. 'REJECT', 'GLOBAL', 'DIRECT'}:
  44. result_data.append(filtered)
  45. else:
  46. print(f'选择代理组为 {GROUP}')
  47. exit(1)
  48. print(f'读取所有代理节点, 一共 {len(result_data)} 个节点')
  49. return result_data
  50. except Exception as e:
  51. print(f"Failed to get proxies: {e}")
  52. return []
  53. def switch_proxy(self, proxy_name: str, url_and_port: str) -> None:
  54. # 根据节点名称和代理服务器url, 切换到指定的代理节点
  55. url = f"{url_and_port}/api/proxies/GLOBAL"
  56. data = {"name": proxy_name}
  57. try:
  58. response = httpx.put(url, json=data)
  59. if response.status_code == 204:
  60. print(f"Switched to proxy: {proxy_name}")
  61. else:
  62. print(f"Failed to switch proxy: {response.status_code} - {proxy_name}")
  63. except Exception as e:
  64. print(f"Failed to switch proxy: {e}")
  65. def update_configs(self):
  66. for base_port in self.base_port:
  67. url_and_port = self.base_url + ":" + base_port
  68. key = "/api/configs"
  69. url = url_and_port + key
  70. # 构造 curl 命令
  71. curl_cmd = [
  72. "curl",
  73. "-X", "PATCH",
  74. url,
  75. "-H", "Content-Type: application/json",
  76. "-d", '{"mode": "Global"}'
  77. ]
  78. try:
  79. # 使用 subprocess 运行 curl 命令
  80. result = subprocess.run(curl_cmd, capture_output=True, text=True, check=True)
  81. # 检查 curl 命令的返回状态
  82. if result.returncode != 0:
  83. print(f"请求失败,状态码: {result.returncode}")
  84. print("错误信息:", result.stderr.strip())
  85. except subprocess.CalledProcessError as exc:
  86. print(f"请求失败: {exc}")
  87. print("错误信息:", exc.stderr.strip())
  88. def check_proxy(self, proxy_url, choose_proxy):
  89. encode_proxy_name = quote(choose_proxy, safe="")
  90. command = [
  91. "curl",
  92. "-X", "GET",
  93. f"{proxy_url}/api/proxies/{encode_proxy_name}/delay?timeout=5000&url=http:%2F%2Fwww.gstatic.com%2Fgenerate_204"
  94. ]
  95. try:
  96. result = subprocess.run(command, capture_output=True, text=True, check=True)
  97. print("Output:", result.stdout)
  98. if 'Timeout' in result.stdout:
  99. return False
  100. return True
  101. except subprocess.CalledProcessError as e:
  102. print("Error:", e.stderr)
  103. return False
  104. def main(self) -> None:
  105. self.update_configs()
  106. if not self.all_proxies:
  107. for port_list in self.base_port:
  108. base_url = self.base_url + ":" + port_list
  109. clash_tool_url = f"{base_url}"
  110. self.all_proxies = self.get_all_proxies(clash_tool_url)
  111. if self.all_proxies:
  112. break
  113. if not self.all_proxies:
  114. return
  115. else:
  116. print(f'待切换节点一共 {len(self.all_proxies)} 个')
  117. for base_port in self.base_port:
  118. url_and_port = self.base_url + ":" + base_port
  119. while True:
  120. choose_proxy = random.choice(self.all_proxies)
  121. if choose_proxy in self.used_proxy:
  122. if len(self.used_proxy) >= len(self.all_proxies):
  123. print('=' * 88)
  124. print(f'所有节点已尝试过, 退出')
  125. print('=' * 88)
  126. return
  127. continue
  128. self.switch_proxy(choose_proxy, url_and_port)
  129. self.used_proxy.append(choose_proxy)
  130. if self.check_proxy(url_and_port, choose_proxy):
  131. print(f"代理 {choose_proxy} 切换成功,检测通过!")
  132. print('=' * 88)
  133. break
  134. else:
  135. print(f"{url_and_port} 切换 xxxxxxxx {choose_proxy} xxxxxxxx 检测失败")
  136. time.sleep(1)
  137. if __name__ == "__main__":
  138. manager = ClashProxyManager(BASE_URL, PORT_LIST)
  139. manager.main()