Pillow ImageGrab 模块
下面给你一个 Pillow(PIL Fork)中 ImageGrab 模块 的完整入门指南,包含截图功能、全屏/区域/窗口截取、跨平台支持、实时监控、OCR 配合、自动化脚本等高级应用。
(基于 Pillow ≥ 9.0,Python 3.8+)
1. 安装 Pillow(含抓屏支持)
# Windows / macOS / Linux(需额外依赖)
pip install --upgrade pillow
注意平台支持:
- Windows:原生支持
- macOS:原生支持(Pillow ≥ 3.3)
- Linux:需安装
xlib依赖:pip install pillow sudo apt-get install python3-xlib # Debian/Ubuntu
2. 基本导入
from PIL import ImageGrab
3. 核心功能一览
| 方法 | 作用 | 参数 |
|---|---|---|
ImageGrab.grab(bbox=None) | 截取屏幕 | bbox=(x1,y1,x2,y2) |
ImageGrab.grabclipboard() | 读取剪贴板图像 | 无 |
4. 基础用法:截全屏
# 截取整个屏幕
img = ImageGrab.grab()
img.save("fullscreen.png")
print(f"分辨率: {img.size}")
5. 截取指定区域
# 左上角 (100,100) 到右下角 (500,400)
bbox = (100, 100, 500, 400)
img = ImageGrab.grab(bbox=bbox)
img.save("region.png")
坐标说明:
(0,0)是屏幕 左上角- 多显示器:负坐标表示左侧屏幕
6. 多显示器支持
from PIL import ImageGrab
# 获取所有显示器总尺寸
total_bbox = ImageGrab.grab().getbbox() # (0, 0, 总宽, 总高)
print(f"多屏总尺寸: {total_bbox}")
# 截取第二个显示器(假设分辨率 1920x1080)
img = ImageGrab.grab(bbox=(1920, 0, 3840, 1080))
img.save("second_screen.png")
7. 实时截屏 + 保存为 GIF 动画
import time
from PIL import ImageGrab
def screen_record(duration=5, fps=10, output="screen.gif"):
frames = []
interval = 1 / fps
start = time.time()
while time.time() - start < duration:
img = ImageGrab.grab()
frames.append(img)
time.sleep(interval)
frames[0].save(
output,
save_all=True,
append_images=frames[1:],
duration=int(1000/fps),
loop=0
)
print(f"录制完成: {output}")
# 录制 3 秒 10FPS
screen_record(3, 10, "demo.gif")
8. 截图 + OCR 文字识别(配合 pytesseract)
pip install pytesseract
# Windows 需安装 Tesseract OCR 引擎:https://github.com/UB-Mannheim/tesseract/wiki
import pytesseract
from PIL import ImageGrab
# 配置 tesseract 路径(Windows)
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
def ocr_region(bbox):
img = ImageGrab.grab(bbox=bbox)
text = pytesseract.image_to_string(img, lang='chi_sim+eng') # 支持中英
return text.strip()
# 识别屏幕中间区域文字
text = ocr_region((200, 200, 800, 600))
print("识别结果:", text)
9. 监控屏幕变化(自动截图)
import hashlib
from PIL import ImageGrab, ImageChops
def monitor_screen(bbox=None, interval=1, max_changes=10):
prev = None
changes = 0
while changes < max_changes:
current = ImageGrab.grab(bbox=bbox)
if prev is not None:
diff = ImageChops.difference(prev, current)
if diff.getbbox(): # 有变化
changes += 1
current.save(f"change_{changes}.png")
print(f"检测到变化 #{changes}")
prev = current
time.sleep(interval)
# 监控右下角区域
monitor_screen(bbox=(1000, 600, 1920, 1080), interval=2)
10. 读取剪贴板图像
def paste_from_clipboard():
img = ImageGrab.grabclipboard()
if isinstance(img, Image.Image):
img.save("clipboard.png")
print("剪贴板图像已保存")
elif img is None:
print("剪贴板无图像")
else:
print(f"剪贴板含文件: {img}")
paste_from_clipboard()
11. 高级技巧
11.1 截取特定窗口(Windows 推荐 pywin32)
pip install pywin32
import win32gui
import win32ui
import win32con
from PIL import Image
def grab_window_by_title(title_contains):
hwnd = win32gui.FindWindow(None, None)
windows = []
def enum_handler(hwnd, ctx):
if win32gui.IsWindowVisible(hwnd):
title = win32gui.GetWindowText(hwnd)
if title_contains in title:
windows.append((hwnd, title))
win32gui.EnumWindows(enum_handler, None)
if not windows:
return None
hwnd = windows[0][0]
left, top, right, bot = win32gui.GetWindowRect(hwnd)
w = right - left
h = bot - top
# 创建设备上下文
hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
saveDC.SelectObject(saveBitMap)
saveDC.BitBlt((0,0), (w,h), mfcDC, (0,0), win32con.SRCCOPY)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
im = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hwnd, hwndDC)
return im
# 截取记事本
img = grab_window_by_title("记事本")
if img:
img.save("notepad.png")
11.2 自动截图脚本(定时任务)
import schedule
import time
def job():
img = ImageGrab.grab()
timestamp = time.strftime("%Y%m%d_%H%M%S")
img.save(f"screenshots/{timestamp}.png")
schedule.every(10).minutes.do(job)
while True:
schedule.run_pending()
time.sleep(1)
12. 常见问题 & 解决方案
| 问题 | 原因 | 解决 |
|---|---|---|
ImportError: ImageGrab is not available on this platform | Linux 未安装 python3-xlib | pip install python3-xlib |
| 截图全黑 | macOS 权限不足 | 系统偏好设置 → 安全性与隐私 → 屏幕录制 → 勾选 Python |
| 多屏坐标错误 | 未考虑 DPI 缩放 | 使用 ctypes.windll.shcore.GetScaleFactorForDevice(Windows) |
grab() 卡死 | 截图区域过大 | 限制 bbox 或降低频率 |
13. 跨平台兼容封装
def cross_platform_grab(bbox=None):
try:
return ImageGrab.grab(bbox=bbox)
except Exception as e:
print(f"ImageGrab 失败: {e}")
return None
# 使用
img = cross_platform_grab((0, 0, 800, 600))
14. 官方文档
- https://pillow.readthedocs.io/en/stable/reference/ImageGrab.html
一键截图工具:grab_tool.py
#!/usr/bin/env python3
import argparse
from PIL import ImageGrab
import pyperclip
import os
def main():
parser = argparse.ArgumentParser(description="屏幕截图工具")
parser.add_argument("-r", "--region", nargs=4, type=int, metavar=('x1','y1','x2','y2'), help="指定区域")
parser.add_argument("-c", "--clipboard", action="store_true", help="保存到剪贴板")
parser.add_argument("-o", "--output", help="输出文件名")
args = parser.parse_args()
img = ImageGrab.grab(bbox=args.region)
output = args.output or f"screenshot_{int(time.time())}.png"
img.save(output)
print(f"已保存: {output}")
if args.clipboard:
# Windows/macOS 自动复制到剪贴板
try:
import io
output = io.BytesIO()
img.convert("RGB").save(output, format='BMP')
data = output.getvalue()[14:] # 跳过 BMP 头
import win32clipboard # pip install pywin32
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
win32clipboard.CloseClipboard()
print("已复制到剪贴板")
except:
pass
if __name__ == "__main__":
os.makedirs("screenshots", exist_ok=True)
os.chdir("screenshots")
main()
使用:
python grab_tool.py -r 100 100 500 400 -c -o demo.png
需要我帮你实现 自动监控游戏界面、截图对比找物、自动化测试截图验证、热键截图 等功能吗?直接说需求,我给你完整代码!