You need to enable JavaScript to run this app. Playwright使用Firefox如何简便加载扩展?是否有对应Python实现方案?
优惠活动
大模型
产品
解决方案
定价
更多

Playwright使用Firefox如何简便加载扩展?是否有对应Python实现方案?

Playwright Python目前没有内置的类似Selenium load_extension的快捷方法加载Firefox扩展,也无法仅通过firefox_user_args参数直接实现(Firefox本身没有类似Chrome的--load-extension启动参数),你可以通过以下两种方案实现:

方案1:和JS版逻辑一致的web-ext调用方案

需要先全局安装web-ext工具:npm install -g web-ext

import asyncio
import subprocess
import re
from pathlib import Path
from playwright.async_api import async_playwright

async def main():
    # 替换为你自己的扩展目录路径
    extension_path = Path("./webextension").absolute()
    async with async_playwright() as p:
        # 调用web-ext启动内置Firefox并开启Juggler调试端口
        proc = subprocess.Popen(
            [
                "web-ext", "run",
                "--source-dir", str(extension_path),
                "--firefox", p.firefox.executable_path,
                "--args", "-juggler=1234"
            ],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True
        )
        # 从输出日志提取WebSocket连接端点
        ws_endpoint = None
        juggler_pattern = re.compile(r"Juggler listening on (ws://.+:\d+)")
        for line in iter(proc.stdout.readline, ""):
            match = juggler_pattern.search(line)
            if match:
                ws_endpoint = match.group(1)
                break
        if not ws_endpoint:
            raise RuntimeError("未获取到Juggler调试端点,启动失败")
        # 连接已启动的Firefox实例
        browser = await p.firefox.connect(ws_endpoint=ws_endpoint)
        page = await browser.new_page()
        await page.goto("https://mozilla.org")
        # 此处编写你的业务逻辑
        # ...
        # 资源释放
        await browser.close()
        proc.terminate()

if __name__ == "__main__":
    asyncio.run(main())

方案2:自定义Firefox Profile方案(无Node.js依赖)

不需要安装web-ext,直接构造Firefox配置文件加载扩展,更适合纯Python环境:

import asyncio
import tempfile
import shutil
import json
from pathlib import Path
from playwright.async_api import async_playwright

async def main():
    # 替换为你自己的扩展目录路径
    extension_path = Path("./webextension").absolute()
    # 读取manifest获取扩展ID,也可以手动指定
    with open(extension_path / "manifest.json", "r", encoding="utf-8") as f:
        manifest = json.load(f)
    ext_id = manifest.get("browser_specific_settings", {}).get("gecko", {}).get("id", "custom-extension@example.com")
    # 创建临时Firefox配置目录
    with tempfile.TemporaryDirectory() as temp_profile_dir:
        temp_profile = Path(temp_profile_dir)
        # 创建扩展存放目录
        ext_dir = temp_profile / "extensions"
        ext_dir.mkdir()
        # 复制扩展到对应目录,目录名必须为扩展ID
        target_ext_path = ext_dir / ext_id
        shutil.copytree(extension_path, target_ext_path)
        # 写入配置启用扩展,关闭安全限制
        prefs_config = [
            f'user_pref("extensions.webextensions.uuids", "{{\\"{ext_id}\\":\\"{ext_id}\\"}}");',
            f'user_pref("extensions.enabledAddons", "{ext_id}:{manifest.get("version", "1.0")}");',
            'user_pref("extensions.autoDisableScopes", 0);',
            'user_pref("extensions.enabledScopes", 15);'
        ]
        with open(temp_profile / "prefs.js", "a", encoding="utf-8") as f:
            f.write("\n".join(prefs_config))
        # 启动带自定义配置的Firefox
        async with async_playwright() as p:
            context = await p.firefox.launch_persistent_context(
                user_data_dir=temp_profile_dir,
                headless=False,
                # 若要使用无头模式,Firefox版本≥112时可开启以下参数
                # args=["--headless=new"]
            )
            page = await context.new_page()
            await page.goto("https://mozilla.org")
            # 此处编写你的业务逻辑
            # ...
            await context.close()

if __name__ == "__main__":
    asyncio.run(main())

注意:如果使用打包好的xpi格式扩展,直接将xpi文件重命名为扩展ID.xpi放到extensions目录下即可,无需解压

内容的提问来源于stack exchange,提问作者BunnyHoppin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 18:36:01