浏览器多实例项目的隔离方案
在 Python 实现多浏览器实例的 JavaScript 注入时,要确保 数据隔离、会话隔离、存储隔离,否则多个实例之间可能会共享 Cookie、LocalStorage 或者其他持久化数据,导致数据污染或冲突。以下是一些关键的隔离策略和代码实现。
1. 数据隔离
问题:
- 默认情况下,不同浏览器实例可能会共享同一个 Profile(如 Chrome 账户、缓存等)。
- 共享 LocalStorage 或 SessionStorage 可能导致数据冲突。
解决方案:
- 启动 Chrome 时,使用
--user-data-dir
让每个实例使用独立的数据目录。 - 禁用缓存
--disable-cache
,避免数据复用。 - 运行时清理 LocalStorage 和 SessionStorage。
代码示例(Pyppeteer):
import asyncio
import os
from pyppeteer import launch
async def inject_js(browser_id, url, script):
user_data_dir = f"./chrome_profiles/profile_{browser_id}" # 每个实例独立的用户数据目录
os.makedirs(user_data_dir, exist_ok=True)
browser = await launch(
headless=False,
args=[
'--no-sandbox',
'--disable-cache',
f'--user-data-dir={user_data_dir}', # 使用独立的用户数据目录
]
)
page = await browser.newPage()
await page.goto(url)
# 执行 JavaScript 代码并清理本地存储
await page.evaluate(f"""
{script}
localStorage.clear();
sessionStorage.clear();
""")
print(f"[{browser_id}] 执行完毕")
await browser.close()
async def main():
url = "https://www.example.com"
script = "document.body.style.backgroundColor = 'green';"
tasks = [inject_js(i, url, script) for i in range(5)] # 5 个浏览器实例
await asyncio.gather(*tasks)
asyncio.run(main())
关键点:
- 独立
user-data-dir
:确保不同实例的数据目录不同,防止缓存、Cookie、LocalStorage 共享。 - 清除本地存储:每次执行前,清除
localStorage
和sessionStorage
,避免数据污染。
2. 会话隔离
问题:
- 浏览器实例可能会共享 Cookie、SessionStorage,导致数据不安全或干扰测试。
解决方案:
- 通过 无痕模式(Incognito Mode) 启动浏览器,每个实例都会有独立的会话。
- 显式清除
Cookies
,避免会话共享。
代码示例(Selenium):
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
import multiprocessing
def inject_js_selenium(browser_id, url, script):
print(f"[{browser_id}] 启动浏览器...")
chrome_options = Options()
chrome_options.add_argument("--incognito") # 无痕模式
chrome_options.add_argument("--disable-cache")
chrome_options.add_argument("--disable-application-cache")
driver = webdriver.Chrome(service=Service("/path/to/chromedriver"), options=chrome_options)
driver.get(url)
print(f"[{browser_id}] 注入 JavaScript 代码...")
driver.execute_script(script)
# 清除 Cookie,确保会话隔离
driver.delete_all_cookies()
print(f"[{browser_id}] 注入完成")
driver.quit()
if __name__ == "__main__":
url = "https://www.example.com"
script = "document.body.style.backgroundColor = 'blue';"
processes = []
for i in range(5): # 5个浏览器实例
p = multiprocessing.Process(target=inject_js_selenium, args=(i, url, script))
p.start()
processes.append(p)
for p in processes:
p.join()
关键点:
- 使用
--incognito
选项:避免不同实例共享 SessionStorage。 - 清除 Cookie:
driver.delete_all_cookies()
确保不会话复用。
3. 存储隔离
问题:
- 数据存储可能会发生共享(如 IndexedDB、LocalStorage)。
- 需要在每个实例执行前,清除本地存储和数据库。
解决方案:
- 通过 JavaScript 代码 清除
IndexedDB
、LocalStorage
和SessionStorage
。
代码示例(Pyppeteer):
async def clear_storage(page):
await page.evaluate("""
indexedDB.databases().then(dbs => {
for (let db of dbs) {
indexedDB.deleteDatabase(db.name);
}
});
localStorage.clear();
sessionStorage.clear();
""")
print("存储清理完毕")
async def inject_js(browser_id, url, script):
browser = await launch(headless=False, args=['--no-sandbox'])
page = await browser.newPage()
await page.goto(url)
# 执行 JavaScript 代码并清理存储
await clear_storage(page)
await page.evaluate(script)
print(f"[{browser_id}] 执行完毕")
await browser.close()
async def main():
url = "https://www.example.com"
script = "document.body.style.backgroundColor = 'yellow';"
tasks = [inject_js(i, url, script) for i in range(5)]
await asyncio.gather(*tasks)
asyncio.run(main())
关键点:
indexedDB.deleteDatabase()
:删除 IndexedDB 以防止数据泄漏。- 清理
localStorage
和sessionStorage
,确保不会话存储干扰。
4. 进程隔离
问题:
- 共享浏览器进程可能导致线程安全问题或数据共享。
- 需要确保每个实例运行在独立进程中。
解决方案:
- 通过 多进程
multiprocessing
或asyncio
任务并发,确保每个浏览器实例是独立的进程。
代码示例(多进程 + Selenium):
import multiprocessing
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def start_browser(instance_id):
options = Options()
options.add_argument("--headless")
options.add_argument("--incognito") # 开启无痕模式
options.add_argument(f"--user-data-dir=./chrome_profile_{instance_id}") # 独立数据目录
driver = webdriver.Chrome(options=options)
driver.get("https://www.example.com")
# 注入 JavaScript 代码
driver.execute_script("document.body.style.backgroundColor = 'pink';")
driver.quit()
if __name__ == "__main__":
num_instances = 5 # 启动5个实例
processes = []
for i in range(num_instances):
p = multiprocessing.Process(target=start_browser, args=(i,))
p.start()
processes.append(p)
for p in processes:
p.join()
关键点:
- 独立
user-data-dir
目录,避免多个 Selenium 实例共享数据。 multiprocessing
多进程,确保浏览器实例的完全隔离。
总结
隔离类型 | 方案 | 实现方式 |
---|---|---|
数据隔离 | 独立 user-data-dir 、清除 LocalStorage | --user-data-dir 、localStorage.clear() |
会话隔离 | 开启 --incognito 无痕模式 | delete_all_cookies() |
存储隔离 | 清除 IndexedDB 、LocalStorage、SessionStorage | indexedDB.deleteDatabase() |
进程隔离 | multiprocessing 启动多个浏览器实例 | multiprocessing.Process() |
通过 独立会话、无痕模式、存储清理、进程隔离,可以确保每个浏览器实例完全隔离,不会影响其他实例的数据。