如何在Python Selenium中通过插件每5分钟自动切换代理?
在Python Selenium中实现Chrome代理插件定时切换功能
要实现类似Proxy Switcher的定时切换代理功能,需要改造原有的Chrome代理插件,让它支持动态更新代理配置,再结合Python的定时逻辑触发切换。以下是具体实现步骤:
一、改造Chrome代理插件
1. 更新manifest.json
添加runtime权限以支持消息通信,保留原有必要权限:
manifest_json = """ { "version": "1.0.0", "manifest_version": 2, "name": "Dynamic Chrome Proxy", "permissions": [ "proxy", "tabs", "unlimitedStorage", "storage", "<all_urls>", "webRequest", "webRequestBlocking", "runtime" ], "background": {"scripts": ["background.js"]}, "minimum_chrome_version": "76.0.0" } """
2. 重写background.js
改成支持动态接收代理配置、更新代理设置的逻辑,同时处理认证信息的更新:
background_js = """ // 存储当前代理认证监听器,切换时移除旧监听避免冲突 let authListener = null; // 设置代理的核心函数 function setProxy(proxyConfig) { const config = { mode: "fixed_servers", rules: { singleProxy: { scheme: proxyConfig.scheme, host: proxyConfig.host, port: proxyConfig.port }, bypassList: ["localhost"] } }; // 更新代理系统设置 chrome.proxy.settings.set({value: config, scope: "regular"}, function() {}); // 移除旧的认证监听器 if (authListener) { chrome.webRequest.onAuthRequired.removeListener(authListener); } // 代理需要认证时,添加新的监听器 if (proxyConfig.username && proxyConfig.password) { authListener = function callbackFn(details) { return { authCredentials: { username: proxyConfig.username, password: proxyConfig.password } }; }; chrome.webRequest.onAuthRequired.addListener( authListener, { urls: ["<all_urls>"] }, ['blocking'] ); } } // 监听来自Python的切换指令 chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { if (request.action === "switchProxy") { setProxy(request.proxy); sendResponse({status: "success"}); } return true; } ); """
二、Python端实现定时切换逻辑
使用Selenium控制Chrome,结合定时任务(此处用time.sleep做简单演示,生产环境可改用schedule库),每次切换时向插件发送消息更新代理:
import time from selenium import webdriver from selenium.webdriver.chrome.options import Options import os import zipfile def create_proxy_extension(manifest, background): """生成临时Chrome代理插件压缩包""" extension_dir = "temp_proxy_extension" os.makedirs(extension_dir, exist_ok=True) # 写入插件文件 with open(os.path.join(extension_dir, "manifest.json"), "w") as f: f.write(manifest) with open(os.path.join(extension_dir, "background.js"), "w") as f: f.write(background) # 打包为zip格式 extension_zip = "proxy_extension.zip" with zipfile.ZipFile(extension_zip, "w", zipfile.ZIP_DEFLATED) as zf: zf.write(os.path.join(extension_dir, "manifest.json"), "manifest.json") zf.write(os.path.join(extension_dir, "background.js"), "background.js") # 清理临时目录 for file in os.listdir(extension_dir): os.remove(os.path.join(extension_dir, file)) os.rmdir(extension_dir) return extension_zip def switch_proxy(driver, proxy): """向插件发送消息触发代理切换""" response = driver.execute_script(""" return new Promise((resolve) => { chrome.runtime.sendMessage({ action: "switchProxy", proxy: arguments[0] }, (response) => { resolve(response); }); }); """, proxy) return response def main(): # 替换为你的代理列表 proxy_list = [ {"scheme": "http", "host": "proxy1.example.com", "port": 8080, "username": "user1", "password": "pass1"}, {"scheme": "http", "host": "proxy2.example.com", "port": 8080, "username": "user2", "password": "pass2"}, {"scheme": "http", "host": "proxy3.example.com", "port": 8080, "username": "user3", "password": "pass3"} ] # 创建代理插件 extension_zip = create_proxy_extension(manifest_json, background_js) # 配置Chrome启动选项 chrome_options = Options() chrome_options.add_extension(extension_zip) # 可选:启用无头模式 # chrome_options.add_argument("--headless=new") # 启动Chrome浏览器 driver = webdriver.Chrome(options=chrome_options) try: proxy_index = 0 while True: current_proxy = proxy_list[proxy_index] print(f"切换到代理: {current_proxy['host']}:{current_proxy['port']}") switch_proxy(driver, current_proxy) # 验证代理切换效果(访问IP查询接口) driver.get("https://api.ipify.org") print(f"当前IP: {driver.page_source}") # 停留10秒后切换下一个代理,可根据需求调整时间 time.sleep(10) # 循环切换代理列表 proxy_index = (proxy_index + 1) % len(proxy_list) except KeyboardInterrupt: print("程序已中断") finally: # 清理临时文件并关闭浏览器 os.remove(extension_zip) driver.quit() if __name__ == "__main__": # 引入插件配置 manifest_json = """ { "version": "1.0.0", "manifest_version": 2, "name": "Dynamic Chrome Proxy", "permissions": [ "proxy", "tabs", "unlimitedStorage", "storage", "<all_urls>", "webRequest", "webRequestBlocking", "runtime" ], "background": {"scripts": ["background.js"]}, "minimum_chrome_version": "76.0.0" } """ background_js = """ // 存储当前代理认证监听器,切换时移除旧监听避免冲突 let authListener = null; // 设置代理的核心函数 function setProxy(proxyConfig) { const config = { mode: "fixed_servers", rules: { singleProxy: { scheme: proxyConfig.scheme, host: proxyConfig.host, port: proxyConfig.port }, bypassList: ["localhost"] } }; // 更新代理系统设置 chrome.proxy.settings.set({value: config, scope: "regular"}, function() {}); // 移除旧的认证监听器 if (authListener) { chrome.webRequest.onAuthRequired.removeListener(authListener); } // 代理需要认证时,添加新的监听器 if (proxyConfig.username && proxyConfig.password) { authListener = function callbackFn(details) { return { authCredentials: { username: proxyConfig.username, password: proxyConfig.password } }; }; chrome.webRequest.onAuthRequired.addListener( authListener, { urls: ["<all_urls>"] }, ['blocking'] ); } } // 监听来自Python的切换指令 chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { if (request.action === "switchProxy") { setProxy(request.proxy); sendResponse({status: "success"}); } return true; } ); """ main()
关键说明
- 插件通过Chrome的
runtime.onMessage接口接收Python端的切换指令,动态更新代理配置 - 切换代理时会移除旧的认证监听器,避免重复触发认证逻辑
- Python端使用
execute_script调用Chrome扩展的消息API,实现与插件的通信 - 定时逻辑可替换为
schedule库,实现更复杂的定时规则(如特定时段切换)
内容的提问来源于stack exchange,提问作者Nime Molla Shuvo
相关产品推荐
相关产品推荐

