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

如何自动将Jupyter Notebook含Widgets的单元格内容保存为PNG/PDF/JPG/GIF

Hey Josef, I’ve been in your exact situation before—trying to document widget configurations programmatically can be tricky when the usual nbconvert or HTML exports don’t capture the dynamic state. Let’s break down some practical solutions that should work for you:

Why your previous attempts didn’t work

First, quick context: Directly converting notebooks to HTML with nbconvert doesn’t render interactive widgets because they rely on Jupyter’s frontend runtime to load their state. html2canvas can work, but it needs to run in the same browser context where the widgets are active, which isn’t handled automatically in a standard notebook setup.


Solution 1: Use Selenium for reliable, automated screenshots

This is my go-to for batch capturing widget states because it uses a real browser to fully render the widgets, ensuring all dynamic elements are captured correctly.

Steps:

  1. Install dependencies:

    pip install selenium ipywidgets pillow
    

    You’ll also need a browser driver (e.g., ChromeDriver for Chrome) matching your browser version.

  2. Example code to loop through widget configurations and save screenshots:

    from ipywidgets import VBox, IntSlider, Dropdown
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    import time
    from PIL import Image
    import io
    
    # Create your base widget setup
    slider = IntSlider(min=0, max=100)
    dropdown = Dropdown(options=["Option A", "Option B", "Option C"])
    vbox = VBox([slider, dropdown])
    
    # Configure Selenium to run headless (no visible browser window)
    chrome_options = Options()
    chrome_options.add_argument("--headless=new")
    driver = webdriver.Chrome(options=chrome_options)
    
    # Loop through your widget configurations
    for slider_val in [25, 50, 75]:
        for dropdown_val in dropdown.options:
            # Update widget state
            slider.value = slider_val
            dropdown.value = dropdown_val
            time.sleep(0.2)  # Wait for widget to re-render
    
            # Export widget to HTML string
            widget_html = vbox._repr_html_()
            # Save to a temporary HTML file
            with open("temp_widget.html", "w") as f:
                f.write(f"""
                <html>
                    <head>
                        <!-- Load Jupyter widget CSS/JS to ensure rendering -->
                        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@0.20.0/dist/embed-amd.min.css">
                        <script src="https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@0.20.0/dist/embed-amd.min.js"></script>
                    </head>
                    <body>{widget_html}</body>
                </html>
                """)
    
            # Load the temp file in Selenium
            driver.get("file:///path/to/your/temp_widget.html")
            time.sleep(1)  # Wait for widgets to fully load
    
            # Capture screenshot and save
            screenshot = driver.get_screenshot_as_png()
            img = Image.open(io.BytesIO(screenshot))
            img.save(f"widget_state_slider-{slider_val}_dropdown-{dropdown_val}.png")
    
    # Cleanup
    driver.quit()
    

Solution 2: Use html2canvas directly in the notebook (no external browser)

If you prefer a lighter setup without Selenium, you can run html2canvas directly in the notebook’s frontend via JavaScript, then pass the image data back to Python to save.

Steps:

  1. First, load html2canvas into your notebook:

    from IPython.display import Javascript, display
    
    display(Javascript("""
    // Load html2canvas from CDN
    var script = document.createElement('script');
    script.src = 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js';
    document.head.appendChild(script);
    """))
    
  2. Define helper functions to capture and save the widget:

    import base64
    from PIL import Image
    import io
    
    def save_widget_screenshot(widget, filename):
        # Get the widget's DOM ID (fallback to model ID if no layout ID)
        widget_id = widget.layout.id if widget.layout.id else widget._model_id
        
        # Run html2canvas to capture the widget
        js_code = f"""
        html2canvas(document.getElementById('{widget_id}')).then(canvas => {{
            var dataURL = canvas.toDataURL('image/png');
            // Send the base64 data to Python
            IPython.notebook.kernel.execute(`_save_screenshot_from_base64('${{dataURL}}', '{filename}')`);
        }});
        """
        display(Javascript(js_code))
    
    def _save_screenshot_from_base64(data_url, filename):
        # Parse base64 data and save
        image_data = base64.b64decode(data_url.split(',')[1])
        with open(filename, 'wb') as f:
            f.write(image_data)
        
        # Convert to JPG if needed
        if filename.endswith('.jpg'):
            img = Image.open(io.BytesIO(image_data))
            img.convert('RGB').save(filename)
    
  3. Use it in your configuration loop:

    # Update widget state
    slider.value = 50
    dropdown.value = "Option B"
    # Save screenshot
    save_widget_screenshot(vbox, "widget_state_example.png")
    

Solution 3: Convert to PDF with wkhtmltopdf (for documentation)

If you need PDF outputs instead of images, wkhtmltopdf can convert the widget’s HTML (with proper resources loaded) into a high-quality PDF.

  1. Install wkhtmltopdf (follow instructions for your OS) and the Python wrapper:

    pip install pdfkit
    
  2. Example code:

    import pdfkit
    
    # Export widget HTML with required resources
    widget_html = f"""
    <html>
        <head>
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@0.20.0/dist/embed-amd.min.css">
            <script src="https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@0.20.0/dist/embed-amd.min.js"></script>
        </head>
        <body>{vbox._repr_html_()}</body>
    </html>
    """
    
    # Convert to PDF
    pdfkit.from_string(widget_html, "widget_state.pdf")
    

Key tips for batch processing

  • Always add a small delay (time.sleep() in Python, or setTimeout() in JS) after updating widget state to ensure the UI finishes rendering before capturing.
  • For GIFs of multiple states, use imageio to combine saved PNGs into an animated GIF:
    import imageio
    
    image_paths = ["state1.png", "state2.png", "state3.png"]
    images = [imageio.imread(path) for path in image_paths]
    imageio.mimsave("widget_states.gif", images, duration=0.5)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:18:03