前端代码渲染截图方案

1、pip安装依赖

bash 复制代码
pip install playwright
playwright install chromium

2、apt安装其他依赖

bash 复制代码
sudo apt update && sudo apt install -y libgbm1  libgbm1 libasound2 libxkbcommon0 libcups2 libdrm2 libxdamage1 libpango-1.0-0

3、支持中文字体

bash 复制代码
sudo apt install fonts-wqy-microhei fonts-wqy-zenhei fonts-noto-cjk

注意:和html的字体并不是完全一样,可以进一步优化

4、完整代码

bash 复制代码
from playwright.sync_api import sync_playwright

def html_to_image_sync(html_file_path, output_image_path):
    """同步版本的HTML转图片"""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        
        # 设置更长的超时时间
        page.set_default_timeout(60000)  # 60秒超时
        
        page.set_viewport_size({"width": 375, "height": 600})

        with open(html_file_path, 'r', encoding='utf-8') as file:
            html_content = file.read()

        try:
            # 使用domcontentloaded而不是默认的load,加载更快
            page.set_content(html_content, wait_until="domcontentloaded", timeout=60000)
            
            # 可选:等待特定元素加载完成
            # page.wait_for_selector('.fund-card', timeout=2000)
            
            page.screenshot(path=output_image_path, full_page=True)
            print(f"截图成功: {output_image_path}")
            
        except Exception as e:
            print(f"截图失败: {e}")
        
        finally:
            browser.close()

# 使用同步版本
html_to_image_sync("0010-gemini3.html", "0010-gemini3.png")

建议:可以将图片宽度放大为375的倍数,不然看起来分辨率太小,不清晰

截图效果(+-图片没有加载出来):

html效果:

5、优化代码(图标需要转base64)

bash 复制代码
from playwright.sync_api import sync_playwright
import base64

def html_to_image_sync(html_file_path, output_image_path):
    """优化版本的HTML转图片"""
    with sync_playwright() as p:
        # 启动浏览器,添加网络优化参数
        browser = p.chromium.launch(
            headless=True,
            args=[
                '--disable-web-security',
                '--disable-features=VizDisplayCompositor',
                '--disable-background-timer-throttling',
                '--disable-renderer-backgrounding',
                '--aggressive-cache-discard',
                '--max_old_space_size=4096'
            ]
        )
        
        # 创建页面上下文,设置网络超时
        context = browser.new_context(
            viewport={"width": 375, "height": 600},
            ignore_https_errors=True
        )
        
        page = context.new_page()
        page.set_default_timeout(45000)  # 45秒超时
        page.set_default_navigation_timeout(45000)

        try:
            with open(html_file_path, 'r', encoding='utf-8') as file:
                html_content = file.read()
            
            print("读取HTML文件成功,开始处理外部资源...")
            
            # 方案1: 替换外部图片为base64内联图片
            html_content = replace_external_images_with_base64(html_content)
            
            # 方案2: 或者使用本地SVG图标替换
            # html_content = replace_with_svg_icons(html_content)
            
            print("设置页面内容...")
            # 使用commit而不是domcontentloaded,更快
            page.set_content(html_content, wait_until="commit", timeout=30000)
            
            # 等待字体和样式加载完成
            print("等待页面渲染...")
            page.wait_for_timeout(2000)  # 等待2秒确保CSS应用
            
            # 检查关键元素是否渲染
            try:
                page.wait_for_selector('.fund-card', timeout=5000)
                print("关键元素加载成功")
            except:
                print("关键元素加载超时,继续截图...")
            
            page.screenshot(path=output_image_path, full_page=True, timeout=15000)
            
        except Exception as e:
            print(f"主流程失败: {e}")
        
        finally:
            browser.close()

def replace_external_images_with_base64(html_content):
    """将外部图片替换为base64编码的内联图片"""
    # 简单的加号SVG(灰色)
    plus_svg = '''<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
        <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" fill="#cccccc"/>
    </svg>'''
    
    # 简单的减号SVG(灰色)
    minus_svg = '''<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
        <path d="M19 13H5v-2h14v2z" fill="#cccccc"/>
    </svg>'''
    
    # 刷新图标SVG
    refresh_svg = '''<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
        <path d="M12.8 5.2A6 6 0 0 0 8 2a6 6 0 1 0 4.8 9.6" stroke="#999" stroke-width="1.5" fill="none"/>
        <path d="M12 4l2.8-2.8v4" stroke="#999" stroke-width="1.5" fill="none" stroke-linecap="round"/>
    </svg>'''
    
    # 将SVG转换为base64
    def svg_to_base64(svg_content):
        return "data:image/svg+xml;base64," + base64.b64encode(svg_content.encode('utf-8')).decode('utf-8')
    
    # 替换图片URL
    replacements = {
        'https://img.icons8.com/material-rounded/24/cccccc/plus-math.png': svg_to_base64(plus_svg),
        'https://img.icons8.com/material-rounded/24/cccccc/minus-math.png': svg_to_base64(minus_svg),
        'https://img.icons8.com/ios/50/999999/refresh--v1.png': svg_to_base64(refresh_svg)
    }
    
    for old_url, new_data in replacements.items():
        html_content = html_content.replace(old_url, new_data)
    
    return html_content

def replace_with_svg_icons(html_content):
    """直接使用内联SVG替换img标签"""
    # 加号SVG
    plus_svg = '''<svg width="12" height="12" viewBox="0 0 24 24" fill="#cccccc">
        <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
    </svg>'''
    
    # 减号SVG  
    minus_svg = '''<svg width="12" height="12" viewBox="0 0 24 24" fill="#cccccc">
        <path d="M19 13H5v-2h14v2z"/>
    </svg>'''
    
    # 刷新SVG
    refresh_svg = '''<svg width="16" height="16" viewBox="0 0 50 50" fill="#999999">
        <path d="M25 10c-8.3 0-15 6.7-15 15s6.7 15 15 15 15-6.7 15-15-6.7-15-15-15zm0 28c-7.2 0-13-5.8-13-13s5.8-13 13-13 13 5.8 13 13-5.8 13-13 13z"/>
        <path d="M25 16l-5 5 5 5 5-5-5-5z"/>
    </svg>'''
    
    # 直接替换整个img标签
    html_content = html_content.replace(
        '',
        refresh_svg
    )
    
    html_content = html_content.replace(
        '',
        plus_svg
    )
    
    html_content = html_content.replace(
        '', 
        minus_svg
    )
    
    return html_content

# 使用优化版本
html_to_image_sync("0010-gemini3.html", "0010-gemini3.png")

截图效果:

图标并不是完全一样。这里是自行生成的。需要解决

相关推荐
该怎么办呢2 分钟前
Source/Core/Matrix4.js
前端·javascript
小江的记录本3 分钟前
【MyBatis-Plus】Spring Boot + MyBatis-Plus 进行各种数据库操作(附完整 CRUD 项目代码示例)
java·前端·数据库·spring boot·后端·sql·mybatis
于慨1 小时前
Capacitor
前端
IT凝冬1 小时前
liunx 的 centos7 安装ngin
前端
赵锦川1 小时前
大屏比例缩放
前端·javascript·html
于慨2 小时前
tauri
java·服务器·前端
贼爱学习的小黄2 小时前
NC BIP参照开发
java·前端·nc
小江的记录本2 小时前
【MyBatis-Plus】MyBatis-Plus的核心特性、条件构造器、分页插件、乐观锁插件
java·前端·spring boot·后端·sql·tomcat·mybatis
光影少年3 小时前
如何进行前端性能优化?
前端·性能优化
Dxy12393102163 小时前
js如何把字符串转数字
开发语言·前端·javascript