Skip to content

截图与PDF

Pydoll通过直接使用Chrome DevTools Protocol命令提供强大的截图和PDF生成功能。可以捕获完整页面、特定元素或生成具有精细控制的PDF。

截图

基础页面截图

import asyncio
from pydoll.browser.chromium import Chrome

async def take_page_screenshot():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com')

        # 保存截图到文件
        await tab.take_screenshot('page.png', quality=100)

asyncio.run(take_page_screenshot())

支持的格式

Pydoll基于文件扩展名支持三种图像格式:

# PNG格式(无损,文件较大)
await tab.take_screenshot('screenshot.png', quality=100)

# JPEG格式(有损,文件较小)
await tab.take_screenshot('screenshot.jpeg', quality=85)

# WebP格式(现代、高效)
await tab.take_screenshot('screenshot.webp', quality=90)

格式检测

图像格式由文件扩展名自动确定。使用不支持的扩展名会引发InvalidFileExtension异常。

JPEG格式同时支持.jpg.jpeg.jpg会自动在内部标准化为.jpeg以匹配CDP要求)。

截图参数

参数 类型 默认值 描述
path Optional[str] None 保存截图的文件路径。如果as_base64=False则为必需。
quality int 100 图像质量(0-100)。值越高质量越好,文件越大。
beyond_viewport bool False 捕获整个可滚动页面,而不仅仅是可见区域。
as_base64 bool False 返回base64编码的字符串而不是保存到文件。

完整页面截图

捕获超出可见视口的内容:

async def full_page_screenshot():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com/long-page')

        # 捕获整个页面,包括折叠下方的内容
        await tab.take_screenshot(
            'full-page.png',
            beyond_viewport=True,
            quality=90
        )

性能注意

在非常长的页面上使用beyond_viewport=True可能会消耗大量内存并需要更长的处理时间。

Base64截图

获取截图的base64字符串用于嵌入或通过API发送:

async def base64_screenshot():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com')

        # 获取截图的base64字符串
        screenshot_base64 = await tab.take_screenshot(
            as_base64=True
        )

        # 在HTML img标签中使用
        html = f'<img src="data:image/png;base64,{screenshot_base64}" />'

        # 或通过API发送
        import aiohttp
        async with aiohttp.ClientSession() as session:
            await session.post(
                'https://api.example.com/upload',
                json={'image': screenshot_base64}
            )

元素截图

捕获特定元素而非整个页面:

async def element_screenshot():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com')

        # 截取特定元素(PNG)
        header = await tab.find(tag_name='header')
        await header.take_screenshot('header.png', quality=100)

        # 截取表单(JPEG)
        form = await tab.find(id='login-form')
        await form.take_screenshot('login-form.jpeg', quality=85)

        # 截取图表或图形(WebP)
        chart = await tab.find(class_name='data-visualization')
        await chart.take_screenshot('chart.webp', quality=90)

格式检测

图像格式自动从文件扩展名(.png.jpeg/.jpg.webp)检测。使用不支持的扩展名会引发InvalidFileExtension异常。

自动滚动

捕获元素截图时,Pydoll会在截图前自动将元素滚动到视图中。

元素截图 vs 页面截图

功能 tab.take_screenshot() element.take_screenshot()
范围 整个视口或页面 仅特定元素
格式支持 PNG, JPEG, WebP PNG, JPEG, WebP
超出视口 ✅ 支持 ❌ 不适用
Base64输出 ✅ 支持 ✅ 支持
自动滚动 ❌ 不适用 ✅ 是
使用场景 完整页面捕获 组件隔离、测试

PDF生成

基础PDF导出

将页面转换为打印质量的PDF输出:

import asyncio
from pathlib import Path
from pydoll.browser.chromium import Chrome

async def generate_pdf():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com/document')

        # 使用Path生成PDF
        await tab.print_to_pdf(Path('document.pdf'))

        # 或使用字符串
        await tab.print_to_pdf('document.pdf')

asyncio.run(generate_pdf())

PDF参数

参数 类型 默认值 描述
path Optional[str \| Path] None 保存PDF的文件路径。如果as_base64=False则为必需。
landscape bool False 使用横向方向(相对于纵向)。
display_header_footer bool False 包含浏览器生成的页眉/页脚,带有标题、URL、页码。
print_background bool True 包含背景图形和颜色。
scale float 1.0 页面缩放因子(0.1-2.0)。用于放大/缩小效果。
as_base64 bool False 返回base64编码的字符串而不是保存到文件。

Path vs 字符串

虽然推荐使用pathlibPath对象作为最佳实践以获得更好的路径处理和跨平台兼容性,但如果您愿意,也可以使用普通字符串。

高级PDF选项

import asyncio
from pathlib import Path
from pydoll.browser.chromium import Chrome

async def advanced_pdf():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com/report')

        # 带页眉/页脚的横向PDF
        await tab.print_to_pdf(
            Path('report-landscape.pdf'),
            landscape=True,
            display_header_footer=True,
            print_background=True,
            scale=0.9
        )

        # 无背景的纵向PDF(节省墨水)
        await tab.print_to_pdf(
            Path('report-ink-friendly.pdf'),
            landscape=False,
            print_background=False,
            scale=1.0
        )

asyncio.run(advanced_pdf())

PDF缩放因子

控制PDF输出的缩放级别:

import asyncio
from pathlib import Path
from pydoll.browser.chromium import Chrome

async def scaled_pdfs():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com/content')

        # 缩小内容以在每页上容纳更多
        await tab.print_to_pdf(Path('compact.pdf'), scale=0.7)

        # 正常缩放
        await tab.print_to_pdf(Path('normal.pdf'), scale=1.0)

        # 放大内容(页数更少)
        await tab.print_to_pdf(Path('large.pdf'), scale=1.5)

asyncio.run(scaled_pdfs())

缩放限制

scale参数接受0.12.0之间的值。超出此范围的值可能产生意外结果。

Base64 PDF

生成PDF的base64字符串用于API传输:

import asyncio
from pydoll.browser.chromium import Chrome

async def base64_pdf():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com/invoice')

        # 获取PDF的base64(无需路径)
        pdf_base64 = await tab.print_to_pdf(as_base64=True)

        # 通过API发送
        import aiohttp
        async with aiohttp.ClientSession() as session:
            await session.post(
                'https://api.example.com/invoices',
                json={'pdf': pdf_base64}
            )

asyncio.run(base64_pdf())

CDP参考

有关这些命令的完整CDP文档,请参阅:

错误处理

from pydoll.exceptions import (
    InvalidFileExtension,
    MissingScreenshotPath,
    TopLevelTargetRequired
)

async def safe_screenshot():
    async with Chrome() as browser:
        tab = await browser.start()
        await tab.go_to('https://example.com')

        try:
            # 缺少路径且as_base64=False
            await tab.take_screenshot()
        except MissingScreenshotPath:
            print("错误:必须提供路径或设置as_base64=True")

        try:
            # 无效的扩展名
            await tab.take_screenshot('image.bmp')
        except InvalidFileExtension as e:
            print(f"错误:{e}")

        # IFrame截图限制
        iframe_element = await tab.find(tag_name='iframe')
        frame = await tab.get_frame(iframe_element)

        try:
            # 这对iframe不起作用
            await frame.take_screenshot('iframe.png')
        except TopLevelTargetRequired:
            print("对iframe内容使用element.take_screenshot()")

            # 正确方法
            content = await frame.find(id='content')
            await content.take_screenshot('iframe-content.jpeg')

了解更多

有关截图和PDF如何与Pydoll架构集成的更多信息:

截图和PDF是自动化、测试和文档编制的必备工具。Pydoll的直接CDP集成提供专业级输出和精细控制。