Python使用Pillow和pyautogui实现全屏截图代码

月亮慢半拍
月亮慢半拍
发布时间:2026-11-04 | 9人浏览过
原创

详细讲解在Python中使用Pillow的ImageGrab与PyAutoGUI实现全屏截图的完整代码、环境依赖配置、底层调用原理、多显示器捕获及Retina高分屏DPI坐标对齐方案。

分类:Python实用指南 阅读时长:约 7 分钟 关键词:Pillow / PyAutoGUI / 全屏截图
Python使用Pillow和pyautogui实现全屏截图代码
文章导读图:基于 Pillow 与 PyAutoGUI 的屏幕捕获模型与技术层级
在 Python 中实现全屏截图,最直接且经过广泛生产验证的方法是使用 Pillow 库的 ImageGrab 模块或 PyAutoGUI 库的 screenshot() 函数。Pillow 的调用路径短、执行性能高,适合纯粹的图像获取、保存与后端处理;PyAutoGUI 则将截图能力与键鼠自动化控制无缝打通,适合构建桌面自动化机器人与 UI 自动化测试。本文完整展示两套方案的基础代码、进阶扩展(如多显示器抓取与内存流中转),并深入剖析高分屏(Retina / DPI)缩放机制与平台权限注意事项。

一、准备工作:依赖安装与系统环境核验

在编写代码前,需要确保运行环境中已正确安装对应的第三方库。在命令行终端中执行以下命令进行安装:

pip install pillow pyautogui

安装完成后,可以在 Python 交互环境中快速核对模块是否能够正常导入:

python -c "import PIL; import pyautogui; print('环境准备就绪')"

不同操作系统在底层图形捕获上的支持机制不同,在正式运行前应特别注意以下系统特有配置:

  • Windows 系统:开箱即用。Windows 底层基于标准 GDI 接口捕获桌面位图,普通用户权限即可正常运行,无额外弹窗权限阻拦。
  • macOS 系统:自 macOS 10.15 (Catalina) 起,系统引入了 TCC 隐私保护机制。首次运行截图脚本的终端程序(如 Terminal、iTerm2)或集成开发环境(如 VS Code、PyCharm)必须在“系统设置 -> 隐私与安全性 -> 屏幕录制”中勾选授权。如果未授权,调用截图接口不会直接抛出异常,而是会截出一张仅有系统桌面壁纸或全黑的空图片。
  • Linux 系统:若运行在 X11 桌面环境,PyAutoGUI 通常依赖 scrot 命令行工具,可以通过 sudo apt-get install scrot(Debian/Ubuntu)补齐;若运行在无图形界面的云服务器(Headless),则需要借助 Xvfb 提供虚拟显示缓冲区。
Python使用Pillow和pyautogui实现全屏截图代码
图 1:全屏截图核心实施流程(环境安装、系统授权、代码调用与输出校验)

二、使用 Pillow (ImageGrab) 实现全屏截图

Pillow 是 Python 中最常用的图像处理基础库。其内置的 ImageGrab 模块提供了原生的屏幕位图捕获能力,无需额外安装庞大的自动化套件。

1. 基础全屏截图代码

以下为使用 Pillow 抓取当前屏幕并保存到磁盘的完整代码:

from PIL import ImageGrab

def capture_fullscreen_pillow(save_path="fullscreen_pillow.png"):
    # 截取主屏幕全屏,返回 PIL.Image.Image 对象
    screenshot = ImageGrab.grab()
    
    # 将图像保存至指定文件路径
    screenshot.save(save_path)
    
    # 打印截图基本信息进行校验
    print(f"Pillow 截图完成!尺寸: {screenshot.size},色彩模式: {screenshot.mode}")
    return screenshot

if __name__ == "__main__":
    capture_fullscreen_pillow()

ImageGrab.grab() 方法在不传任何参数时,默认抓取主显示器的全屏区域,返回一个 PIL.Image.Image 对象。该对象可以直接调用 save() 保存为常见的图像格式(如 PNG、JPEG、WEBP 等)。如果保存为 JPEG 格式,还可以通过传递 quality=85 参数来兼顾清晰度与文件体积。

2. 多显示器(多屏幕)全景截图

在双屏或多屏开发环境中,很多读者希望一次性截取所有显示器的完整拼合画面。在 Pillow 中,只需向 grab() 传递 all_screens=True 参数即可实现:

from PIL import ImageGrab

# 启用 all_screens 参数抓取所有连接的显示器
multiscreen_img = ImageGrab.grab(all_screens=True)
multiscreen_img.save("multiscreen_pillow.png")
print(f"多显示器拼接全景分辨率: {multiscreen_img.size}")
多屏注意事项

all_screens=True 目前在 Windows 和 macOS 系统下均受支持。当两个显示器的物理分辨率或缩放比例不同时,Pillow 会以包容所有屏幕的最小外接矩形构建图像画布,未被屏幕覆盖的留白区域默认填充为黑色。

三、使用 PyAutoGUI 实现全屏截图

PyAutoGUI 是一个跨平台的 GUI 自动化控制库。如果你的截图需求是“截取屏幕 -> 寻找目标按钮 -> 控制鼠标点击”自动化工作流中的一环,使用 PyAutoGUI 可以让代码结构更为简练。

1. 基础全屏截图代码

PyAutoGUI 的 screenshot() 函数支持直接传入文件名进行保存,也可以像 Pillow 一样返回 Image 对象:

import pyautogui

def capture_fullscreen_pyautogui(save_path="fullscreen_pyautogui.png"):
    # 一行代码完成全屏截图并写入文件
    # 若不传入参数,则只在内存中返回 Image 对象而不写入硬盘
    screenshot = pyautogui.screenshot(save_path)
    
    # 获取逻辑屏幕尺寸供自动化定位对比
    screen_width, screen_height = pyautogui.size()
    print(f"PyAutoGUI 截图保存成功!逻辑屏幕分辨率: {screen_width}x{screen_height}")
    return screenshot

if __name__ == "__main__":
    capture_fullscreen_pyautogui()

2. 配合延迟倒计时截图

在实际自动化测试中,常常需要在用户打开特定窗口或弹出菜单后再触发截图。可以结合 Python 标准库的 time.sleep() 实现倒计时截屏:

import time
import pyautogui

def delayed_capture(countdown=3, save_path="delayed_screenshot.png"):
    print(f"请切换到目标窗口,将在 {countdown} 秒后执行全屏截图...")
    for i in range(countdown, 0, -1):
        print(f"倒计时: {i} 秒")
        time.sleep(1)
        
    img = pyautogui.screenshot(save_path)
    print(f"已截屏并保存至: {save_path}")

if __name__ == "__main__":
    delayed_capture(3)

四、底层调用机制与架构关系剖析

许多初学者会好奇:Pillow 与 PyAutoGUI 在全屏截图上是否存在本质差异?

答案是:在 Windows 和 macOS 系统中,PyAutoGUI 的 screenshot() 函数底层直接委托调用了 Pillow 的 ImageGrab.grab()。PyAutoGUI 内部在导入阶段会检测系统中是否安装了 Pillow;如果存在 Pillow,它便将抓取屏幕的底层工作交由 Pillow 执行。

Python使用Pillow和pyautogui实现全屏截图代码
图 2:Pillow 与 PyAutoGUI 截图架构与底层原理分层图

通过架构图可以清晰看出两者的层级差异:

  • Pillow (ImageGrab):属于轻量级纯图像库。它编译了原生 C 扩展,直接对接 Windows GDI(通过 BitBlt 复制设备上下文 DC)或 macOS Quartz CoreGraphics 框架(通过 CGWindowListCreateImage 提取显存图像缓存)。
  • PyAutoGUI:属于高阶综合库。它在 Pillow 基础之上包装了统一的跨平台调用外观,并补充了键鼠消息模拟、屏幕模板匹对(locateOnScreen)等自动化生态支持。在缺少 Pillow 的 Linux 环境下,它会降级通过调用 scrot 命令行工具来完成截图。

五、高分屏 (Retina / Windows DPI) 缩放与像素对齐

在搭载 2K/4K 屏幕的高分屏笔记本或启用了 Retina 视网膜屏的 Mac 电脑上,读者常常会遇到一个令人困惑的问题:

运行 pyautogui.size() 显示屏幕尺寸为 (1920, 1080),但保存出来的截图文件查看详细属性却发现尺寸是 (3840, 2160)。如果在截图上测量了一个按钮的像素坐标 (800, 600) 并直接调用 pyautogui.click(800, 600),鼠标往往会点击在完全错误的位置。

Python使用Pillow和pyautogui实现全屏截图代码
图 3:高分屏 (Retina / DPI) 缩放与像素坐标映射关系细节

这一现象的根源在于逻辑视口坐标(Logical Points)与物理像素矩阵(Physical Pixels)的分离:

  1. 逻辑坐标(UI 坐标):操作系统为了防止在高分屏下文字和图标过小,设置了 150%、200%(2.0x)甚至更高的 DPI 缩放比率。pyautogui.size() 和 pyautogui.click() 使用的就是这种经过缩放的逻辑度量单位。
  2. 物理位图:ImageGrab.grab() 截取的是显卡渲染帧缓冲区中的真实物理像素点,因此图像尺寸会被完整放大 2 倍。

坐标换算的正确做法:如果通过图像识别找到了截图中的目标中心点 (img_x, img_y),需要先除以缩放系数,再传递给 PyAutoGUI 进行点击:

import pyautogui
from PIL import ImageGrab

# 1. 抓取物理像素图像
shot = ImageGrab.grab()
physical_w, physical_h = shot.size

# 2. 获取逻辑分辨率
logical_w, logical_h = pyautogui.size()

# 3. 计算缩放倍率(例如 Retina 屏通常为 2.0)
scale_x = physical_w / logical_w
scale_y = physical_h / logical_h

# 假设在物理截图中识别出目标位于 (800, 600)
target_img_x, target_img_y = 800, 600

# 4. 换算为逻辑坐标后点击
real_click_x = target_img_x / scale_x
real_click_y = target_img_y / scale_y

print(f"缩放倍率: {scale_x},实际应点击坐标: ({real_click_x}, {real_click_y})")
# pyautogui.click(real_click_x, real_click_y)

六、进阶技巧:无磁盘 IO 的内存流中转

在网络爬虫、远程监控或 Web API 接口开发中,频繁将截图写入本地固态硬盘再读取会带来不必要的磁盘磨损与 I/O 延迟。可以通过 Python 标准库中的 io.BytesIO 将截图保存在内存中:

import io
from PIL import ImageGrab

def get_screenshot_bytes(image_format="PNG"):
    # 截取全屏
    img = ImageGrab.grab()
    
    # 创建内存二进制流缓冲区
    buffer = io.BytesIO()
    
    # 写入内存缓冲区而非硬盘
    img.save(buffer, format=image_format)
    
    # 获取字节数据(可直接用于网络传输或 Base64 编码)
    img_bytes = buffer.getvalue()
    buffer.close()
    
    print(f"已在内存中生成 {image_format} 截图流,总大小: {len(img_bytes)} 字节")
    return img_bytes

if __name__ == "__main__":
    raw_data = get_screenshot_bytes("PNG")

七、常见故障排查与运行避坑

故障现象 根本原因 排查与解决方法
macOS 下截图全黑或只有桌面背景 当前运行终端或 IDE 未获得系统的“屏幕录制”授权 前往“系统设置 -> 隐私与安全性 -> 屏幕录制”,找到当前运行的 Python、VS Code 或 Terminal,打开授权开关并重启应用。
Linux 无桌面服务器下报找不到显示设备 无 X11 图形环境(Headless 环境未指定 DISPLAY 变量) 使用虚拟帧缓冲:sudo apt install xvfb,使用 xvfb-run python your_script.py 运行。
Linux 报错 scrot not found 未预装底层截图工具 在终端执行 sudo apt-get install scrot 完成系统级命令安装。
截图文件体积过大(单张 10MB+) 高分屏多屏幕全景采用无损 PNG 编码保存 使用 JPEG 或 WEBP 格式并设置合理画质参数:img.save('output.jpg', quality=85, optimize=True)。

八、方案选型与特性总结

综合来看,Pillow 与 PyAutoGUI 各有侧重。选择哪一个取决于你的核心业务逻辑:

Python使用Pillow和pyautogui实现全屏截图代码
图 4:Pillow 与 PyAutoGUI 技术特性对比与选型决策指南

简明选型结论:

  • 如果你只需要定时抓取屏幕、做图像分析、多屏巡检或将截图通过 API 发送,优先选用 Pillow (ImageGrab)。它的依赖极小、速度更快,且对多屏拼接支持更为原生态。
  • 如果截图是为了后续进行自动化按钮识别、鼠标连点、按键模拟或 RPA 脚本开发,优先选用 PyAutoGUI,一套套件即可串联整个自动化执行链路。
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表