🎨 feat(getip): 重构 getip.py 并更新代理获取逻辑- 在 getip.py 中添加类型注解和函数文档字符串

- 修改 newip 函数以返回代理 IP 池列表
- 更新 ProxyCat-V1.9.py 中的代理加载逻辑
-调整 README.md 中关于 getip.py 的说明
This commit is contained in:
祖国滴°花朵 2024-11-28 11:59:27 +08:00
parent 18dd05a785
commit da2f4c8835
3 changed files with 63 additions and 52 deletions

View File

@ -7,6 +7,8 @@ from banner import print_banner
from itertools import cycle
init(autoreset=True)
class ColoredFormatter(logging.Formatter):
COLORS = {
logging.INFO: Fore.GREEN,
@ -20,6 +22,7 @@ class ColoredFormatter(logging.Formatter):
record.msg = f"{log_color}{record.msg}{Style.RESET_ALL}"
return super().format(record)
log_format = '%(asctime)s - %(levelname)s - %(message)s'
formatter = ColoredFormatter(log_format)
@ -28,14 +31,17 @@ console_handler.setFormatter(formatter)
logging.basicConfig(level=logging.INFO, handlers=[console_handler])
def load_proxies(file_path='ip.txt'):
with open(file_path, 'r') as file:
return [line.strip() for line in file if '://' in line]
def validate_proxy(proxy):
pattern = re.compile(r'^(?P<scheme>socks5|http|https)://(?P<host>[^:]+):(?P<port>\d+)$')
return pattern.match(proxy) is not None
class AsyncProxyServer:
def __init__(self, config):
self.config = {**DEFAULT_CONFIG, **config}
@ -54,20 +60,9 @@ class AsyncProxyServer:
self.proxy_failed = False
def load_proxies(self):
proxies = load_proxies(self.proxy_file)
proxies = getip.newip() if self.use_getip else load_proxies(self.proxy_file)
valid_proxies = [p for p in proxies if validate_proxy(p)]
if self.use_getip:
valid_proxies = []
for _ in range(4):
new_ip = getip.newip()
if validate_proxy(new_ip):
valid_proxies.append(new_ip)
break
else:
logging.error("多次尝试获取有效代理失败,退出程序")
exit(1)
return valid_proxies
async def get_next_proxy(self):
@ -90,7 +85,8 @@ class AsyncProxyServer:
return self.proxies[0] if self.proxies else "没有可用的代理"
def time_until_next_switch(self):
return float('inf') if self.mode == 'load_balance' else max(0, self.interval - (time.time() - self.last_switch_time))
return float('inf') if self.mode == 'load_balance' else max(0, self.interval - (
time.time() - self.last_switch_time))
async def acquire(self):
await self.rate_limiter.put(None)
@ -179,7 +175,10 @@ class AsyncProxyServer:
await remote_writer.drain()
await remote_reader.readexactly(2)
remote_writer.write(b'\x05\x01\x00' + (b'\x03' + len(dst_addr).to_bytes(1, 'big') + dst_addr.encode() if isinstance(dst_addr, str) else b'\x01' + socket.inet_aton(dst_addr)) + struct.pack('!H', dst_port))
remote_writer.write(b'\x05\x01\x00' + (
b'\x03' + len(dst_addr).to_bytes(1, 'big') + dst_addr.encode() if isinstance(dst_addr,
str) else b'\x01' + socket.inet_aton(
dst_addr)) + struct.pack('!H', dst_port))
await remote_writer.drain()
await remote_reader.readexactly(10)
@ -235,7 +234,8 @@ class AsyncProxyServer:
continue
if self.auth_required and not self._authenticate(headers):
writer.write(b'HTTP/1.1 407 Proxy Authentication Required\r\nProxy-Authenticate: Basic realm="Proxy"\r\n\r\n')
writer.write(
b'HTTP/1.1 407 Proxy Authentication Required\r\nProxy-Authenticate: Basic realm="Proxy"\r\n\r\n')
await writer.drain()
return
@ -281,7 +281,8 @@ class AsyncProxyServer:
proxy_port = int(proxy_port)
try:
remote_reader, remote_writer = await asyncio.wait_for(asyncio.open_connection(proxy_host, proxy_port),timeout=10)
remote_reader, remote_writer = await asyncio.wait_for(asyncio.open_connection(proxy_host, proxy_port),
timeout=10)
if proxy_type == 'http':
connect_headers = [f'CONNECT {host}:{port} HTTP/1.1', f'Host: {host}:{port}']
@ -300,7 +301,8 @@ class AsyncProxyServer:
remote_writer.write(b'\x05\x01\x00')
await remote_writer.drain()
if (await remote_reader.read(2))[1] == 0:
remote_writer.write(b'\x05\x01\x00\x03' + len(host).to_bytes(1, 'big') + host.encode() + port.to_bytes(2, 'big'))
remote_writer.write(
b'\x05\x01\x00\x03' + len(host).to_bytes(1, 'big') + host.encode() + port.to_bytes(2, 'big'))
await remote_writer.drain()
if (await remote_reader.read(10))[1] != 0:
raise Exception("Bad Gateway")
@ -400,6 +402,7 @@ class AsyncProxyServer:
writer.write(b'0\r\n\r\n')
await writer.drain()
def update_status(server):
while True:
if server.mode == 'load_balance':
@ -410,6 +413,7 @@ def update_status(server):
print(status, end='', flush=True)
time.sleep(1)
async def handle_client_wrapper(server, reader, writer, clients):
task = asyncio.create_task(server.handle_client(reader, writer))
clients.add(task)
@ -420,11 +424,13 @@ async def handle_client_wrapper(server, reader, writer, clients):
finally:
clients.remove(task)
async def run_server(server):
clients = set()
server_instance = None
try:
server_instance = await asyncio.start_server(lambda r, w: handle_client_wrapper(server, r, w, clients),'0.0.0.0', int(server.config['port']))
server_instance = await asyncio.start_server(lambda r, w: handle_client_wrapper(server, r, w, clients),
'0.0.0.0', int(server.config['port']))
async with server_instance:
await server_instance.serve_forever()
except asyncio.CancelledError:
@ -437,6 +443,7 @@ async def run_server(server):
client.cancel()
await asyncio.gather(*clients, return_exceptions=True)
async def run_proxy_check(server):
if server.config.get('check_proxies', 'False').lower() == 'true':
logging.info("开始检测代理地址...")
@ -451,6 +458,7 @@ async def run_proxy_check(server):
else:
logging.info("代理检测已禁用")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=logoprint.logos())
parser.add_argument('-c', '--config', default='config.ini', help='配置文件路径')

View File

@ -1,12 +1,15 @@
import requests
from typing import List
def newip():
def newip() -> List[str]:
"""
自定义获取新的代理IP池
:return: 返回代理IP池列表形如['http://127.0.0.1:10809', 'socks5://127.0.0.1:10808']
"""
print("正在获取新的代理IP")
url = f""
response = requests.get(url)
response.raise_for_status()
newip = "socks5://"+response.text.split("\r\n")[0]
print("新的代理IP为:"+newip)
return newip
proxy = ['http://127.0.0.1:10809', 'socks5://127.0.0.1:10808', 'http://127.0.0.1:1089', 'socks5://127.0.0.1:1088']
return proxy

View File

@ -151,7 +151,7 @@ socks5://127.0.0.1:1080
工具支持直接调用代理地址获取的API接口。当您配置 `use_getip = True` 时,工具将不再从本地 `ip.txt` 中读取代理地址,而是通过执行 **getip.py** 脚本来获取新的代理地址请确保您的IP已加白名单
此时,您需要将 **getip.py** 的内容修改为您自己的接口,格式为 `IP:PORT`。默认为 `socks5` 协议,如需使用 `http`,请手动更改。
此时,您需要将 **getip.py** 的内容修改为您自己的接口,返回代理IP池列表例如['http://127.0.0.1:10809', 'socks5://127.0.0.1:10808']
## 性能表现