macOS下Python实现指定窗口(含后台)截图并提取文本的方法问询
在macOS下捕获指定窗口(含后台窗口)的屏幕截图并提取文本
实现思路
在macOS上捕获指定窗口(无论前台/后台、是否移动),需要借助系统原生的Quartz框架获取窗口信息并捕获截图,替换原代码中基于固定区域的截图逻辑。
依赖安装
先安装所需Python库:
pip install pyobjc-core pyobjc-framework-Quartz pytesseract schedule pillow
修改后的完整代码
import pytesseract import schedule import time from Quartz import ( CGWindowListCopyWindowInfo, kCGWindowListOptionAll, kCGNullWindowID, CGWindowImageCreate, kCGWindowImageBoundsIgnoreFraming, CFURLCreateWithFileSystemPath, kCFURLPOSIXPathStyle, kCFAllocatorDefault, CGImageDestinationCreateWithURL, CGImageDestinationAddImage, CGImageDestinationFinalize ) from PIL import Image # 配置:替换为你的目标窗口标题(或应用名称) TARGET_WINDOW_TITLE = "Notes" # 示例:捕获系统笔记应用窗口 output_file = 'captured_text.txt' last_text = "" def get_window_id_by_title(window_title): """根据窗口标题或应用名称查找窗口ID""" window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID) for window in window_list: if (window_title in window.get('kCGWindowName', '') or window_title in window.get('kCGWindowOwnerName', '')): return window['kCGWindowNumber'] return None def capture_window_screenshot(window_id): """根据窗口ID捕获截图,返回PIL图像""" window_image = CGWindowImageCreate( None, window_id, None, kCGWindowImageBoundsIgnoreFraming ) if not window_image: return None # 将CGImage临时保存为PNG,转换为PIL图像 temp_path = "/tmp/window_screenshot.png" url = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, temp_path, kCFURLPOSIXPathStyle, False ) dest = CGImageDestinationCreateWithURL(url, 'public.png', 1, None) CGImageDestinationAddImage(dest, window_image, None) CGImageDestinationFinalize(dest) return Image.open(temp_path) def capture_and_recognize(): global last_text window_id = get_window_id_by_title(TARGET_WINDOW_TITLE) if not window_id: print(f"未找到标题包含'{TARGET_WINDOW_TITLE}'的窗口") return screenshot = capture_window_screenshot(window_id) if not screenshot: print("窗口截图失败") return text = pytesseract.image_to_string(screenshot, lang='eng', config='--psm 6').strip() if text and text != last_text: with open(output_file, 'a') as f: f.write(text + '\n') print(f"Captured Text: {text}") last_text = text # 调度任务(每0.5秒执行一次) schedule.every(0.5).seconds.do(capture_and_recognize) print("Starting text capture... Press Ctrl+C to stop.") try: while True: schedule.run_pending() time.sleep(0.1) except KeyboardInterrupt: print("Text capture stopped.")
关键说明
- 窗口匹配:代码同时支持匹配窗口标题(
kCGWindowName)和应用名称(kCGWindowOwnerName),如果目标窗口无明确标题,可直接填写应用名称(如"TextEdit"、"Safari")。 - 权限设置:macOS会要求授予屏幕录制权限,需在「系统设置 > 隐私与安全性 > 屏幕录制」中添加你的Python解释器或IDE。
- 后台窗口支持:借助Quartz的
CGWindowImageCreateAPI,可直接捕获后台窗口内容,无需窗口处于前台。 - 自动适配:自动获取窗口当前位置和尺寸,窗口移动后仍能正确捕获,无需手动调整区域参数。
内容的提问来源于stack exchange,提问作者Nina W.
相关产品推荐
相关产品推荐

