如何在Python中配置带账号密码验证的代理连接
为Windows系统代理添加自动认证功能
你的现有脚本通过WinINet API设置了系统代理的IP和端口,但WinINet的INTERNET_PER_CONN_OPTION结构不直接支持配置代理认证信息。要实现自动账号密码登录,需要额外调用InternetSetOptionW来设置代理的用户名和密码,具体修改方案如下:
修改后的完整代码
from ctypes import * from ctypes.wintypes import * LPWSTR = POINTER(WCHAR) HINTERNET = LPVOID # 原有常量 INTERNET_PER_CONN_PROXY_SERVER = 2 INTERNET_OPTION_REFRESH = 37 INTERNET_OPTION_SETTINGS_CHANGED = 39 INTERNET_OPTION_PER_CONNECTION_OPTION = 75 INTERNET_PER_CONN_PROXY_BYPASS = 3 INTERNET_PER_CONN_FLAGS = 1 # 新增代理认证相关常量 INTERNET_OPTION_PROXY_USERNAME = 83 INTERNET_OPTION_PROXY_PASSWORD = 84 class INTERNET_PER_CONN_OPTION(Structure): class Value(Union): _fields_ = [ ('dwValue', DWORD), ('pszValue', LPWSTR), ('ftValue', FILETIME), ] _fields_ = [ ('dwOption', DWORD), ('Value', Value), ] class INTERNET_PER_CONN_OPTION_LIST(Structure): _fields_ = [ ('dwSize', DWORD), ('pszConnection', LPWSTR), ('dwOptionCount', DWORD), ('dwOptionError', DWORD), ('pOptions', POINTER(INTERNET_PER_CONN_OPTION)), ] def set_proxy_settings(ip, port, username=None, password=None, on=True): if on: setting = create_unicode_buffer(ip + ":" + str(port)) else: setting = None InternetSetOption = windll.wininet.InternetSetOptionW InternetSetOption.argtypes = [HINTERNET, DWORD, LPVOID, DWORD] InternetSetOption.restype = BOOL # 设置代理服务器、绕过列表等基础配置 List = INTERNET_PER_CONN_OPTION_LIST() OptionCount = 3 if on else 1 Option = (INTERNET_PER_CONN_OPTION * OptionCount)() nSize = c_ulong(sizeof(INTERNET_PER_CONN_OPTION_LIST)) Option[0].dwOption = INTERNET_PER_CONN_FLAGS Option[0].Value.dwValue = (2 if on else 1) # 2=使用代理,1=直接连接 if on: Option[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER Option[1].Value.pszValue = setting Option[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS Option[2].Value.pszValue = create_unicode_buffer( "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;172.32.*;192.168.*") List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST) List.pszConnection = None # 应用于所有连接 List.dwOptionCount = OptionCount List.dwOptionError = 0 List.pOptions = Option # 应用基础代理设置 InternetSetOption(None, INTERNET_OPTION_PER_CONNECTION_OPTION, byref(List), nSize) # 如果开启代理且提供了账号密码,设置代理认证信息 if on and username and password: # 设置用户名 username_buf = create_unicode_buffer(username) InternetSetOption(None, INTERNET_OPTION_PROXY_USERNAME, username_buf, sizeof(username_buf)) # 设置密码 password_buf = create_unicode_buffer(password) InternetSetOption(None, INTERNET_OPTION_PROXY_PASSWORD, password_buf, sizeof(password_buf)) # 刷新代理设置 InternetSetOption(None, INTERNET_OPTION_SETTINGS_CHANGED, None, 0) InternetSetOption(None, INTERNET_OPTION_REFRESH, None, 0)
调用示例
# 带认证的代理设置 set_proxy_settings("217.218.242.75", 5678, username="your_user", password="your_pass", on=True) # 关闭代理 set_proxy_settings("", 0, on=False)
关键说明
- 新增常量:引入
INTERNET_OPTION_PROXY_USERNAME(83)和INTERNET_OPTION_PROXY_PASSWORD(84)两个选项,用于传递代理的认证信息。 - 参数扩展:给
set_proxy_settings函数添加username和password可选参数,只有开启代理且提供这两个参数时才会设置认证。 - 内存管理:使用
create_unicode_buffer创建宽字符缓冲区,确保WinINet API能正确读取字符串内容。 - 刷新设置:完成所有配置后,必须调用
INTERNET_OPTION_SETTINGS_CHANGED和INTERNET_OPTION_REFRESH让系统和应用加载新的代理配置。
注意:部分应用可能不会自动读取系统代理的认证信息,这类场景下需要针对应用单独处理,但上述代码已覆盖Windows系统级代理的自动认证需求。
内容的提问来源于stack exchange,提问作者MoXiTo
相关产品推荐
相关产品推荐

