You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Playwright加载本地HTML时无法获取JSON数据的问题

问题描述

尝试通过JavaScript读取本地JSON文件渲染HTML表单,再用Playwright将填充后的表单导出为PDF。但通过file://协议打开本地index.html时,JS无法加载JSON数据,导出的PDF只有纯HTML内容。用本地服务器(如liveserver、node)运行则一切正常,希望不用服务器解决这个问题。

复现代码

gen.py

import os
from playwright.sync_api import sync_playwright

def generate_pdf():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        current_directory = os.getcwd()
        index_html_path = os.path.join(current_directory, 'index.html')
        index_html_url = f'file://{index_html_path}'
        page.goto(index_html_url)
        page.pdf(path='output.pdf')
        browser.close()

generate_pdf()

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Minimal Reproducible Example</title>
    <script src="script.js"></script>
</head>
<body>
    <div id="content"></div>
</body>
</html>

script.js

document.addEventListener("DOMContentLoaded", function () {
    const contentDiv = document.getElementById("content");

    fetch("data.json")
        .then(response => response.json())
        .then(data => {
            const message = data.message;
            contentDiv.innerHTML = `<p>${message}</p>`;
        })
        .catch(error => console.error("Error loading JSON:", error));
});

data.json

{
    "message": "This is dynamic content loaded from a JSON file."
}
问题原因
  1. file://协议安全限制:浏览器出于安全考量,对file://协议下的跨资源请求有严格限制,fetch请求本地JSON文件会被拦截,导致JS无法获取数据。
  2. 未等待JS执行完成:page.goto()默认仅等待DOM加载完成,不会等待异步的fetch请求和动态DOM渲染,生成PDF时内容还未加载完毕。
解决方案

方案1:等待动态内容加载完成

修改Playwright脚本,等待目标元素出现或网络空闲后再生成PDF:

import os
from playwright.sync_api import sync_playwright

def generate_pdf():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        current_directory = os.getcwd()
        index_html_path = os.path.join(current_directory, 'index.html')
        index_html_url = f'file://{index_html_path}'
        page.goto(index_html_url)
        # 等待动态生成的p元素出现
        page.wait_for_selector('#content p')
        # 或等待网络空闲(无请求持续500ms)
        # page.wait_for_load_state('networkidle')
        page.pdf(path='output.pdf')
        browser.close()

generate_pdf()

方案2:解除本地文件访问限制

启动Chromium时添加--allow-file-access-from-files参数,放开file://协议下的跨资源请求限制:

import os
from playwright.sync_api import sync_playwright

def generate_pdf():
    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=True,
            args=["--allow-file-access-from-files"]
        )
        page = browser.new_page()
        current_directory = os.getcwd()
        index_html_path = os.path.join(current_directory, 'index.html')
        index_html_url = f'file://{index_html_path}'
        page.goto(index_html_url)
        page.wait_for_selector('#content p')
        page.pdf(path='output.pdf')
        browser.close()

generate_pdf()

方案3:内嵌JSON数据到HTML

直接将JSON数据写入HTML的<script>标签,避免fetch请求:
修改index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Minimal Reproducible Example</title>
    <script>
        // 内嵌JSON数据
        const formData = {
            "message": "This is dynamic content loaded from a JSON file."
        };
    </script>
    <script src="script.js"></script>
</head>
<body>
    <div id="content"></div>
</body>
</html>

修改script.js:

document.addEventListener("DOMContentLoaded", function () {
    const contentDiv = document.getElementById("content");
    // 直接使用内嵌数据
    const message = formData.message;
    contentDiv.innerHTML = `<p>${message}</p>`;
});

方案4:通过Playwright注入JSON数据

用Playwright读取本地JSON文件,再注入到页面上下文,替代前端fetch:
修改gen.py:

import os
import json
from playwright.sync_api import sync_playwright

def generate_pdf():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        current_directory = os.getcwd()
        
        # 读取本地JSON数据
        json_path = os.path.join(current_directory, 'data.json')
        with open(json_path, 'r') as f:
            form_data = json.load(f)
        
        index_html_path = os.path.join(current_directory, 'index.html')
        index_html_url = f'file://{index_html_path}'
        page.goto(index_html_url)
        
        # 将数据注入页面全局变量
        page.add_init_script(f"window.formData = {json.dumps(form_data)};")
        
        page.wait_for_selector('#content p')
        page.pdf(path='output.pdf')
        browser.close()

generate_pdf()

对应修改script.js:

document.addEventListener("DOMContentLoaded", function () {
    const contentDiv = document.getElementById("content");
    const message = window.formData.message;
    contentDiv.innerHTML = `<p>${message}</p>`;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 01:50:20