Tome la captura de pantalla en Python en Mac OS X

ImageGrab de PIL hubiera sido ideal. Estoy buscando una funcionalidad similar, específicamente la capacidad de definir el cuadro delimitador de la captura de pantalla. He estado buscando una biblioteca para hacerlo en Mac OS X, pero no he tenido suerte. Tampoco pude encontrar ningún código de ejemplo para hacerlo (¿tal vez pyobjc?).

Si bien no es exactamente lo que desea, en un apuro podría usar:

os.system("screencapture screen.png") 

Luego abre esa imagen con el módulo de imagen. Estoy seguro de que existe una mejor solución sin embargo.

Aquí se explica cómo capturar y guardar una captura de pantalla con PyObjC, según mi respuesta aquí.

Puede capturar toda la pantalla o especificar una región para capturar. Si no necesita hacer eso, le recomiendo que simplemente llame al comando screencapture (más funciones, más robusto y más rápido: solo la importación inicial de PyObjC puede tomar alrededor de un segundo)

 import Quartz import LaunchServices from Cocoa import NSURL import Quartz.CoreGraphics as CG def screenshot(path, region = None): """region should be a CGRect, something like: >>> import Quartz.CoreGraphics as CG >>> region = CG.CGRectMake(0, 0, 100, 100) >>> sp = ScreenPixel() >>> sp.capture(region=region) The default region is CG.CGRectInfinite (captures the full screen) """ if region is None: region = CG.CGRectInfinite # Create screenshot as CGImage image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) dpi = 72 # FIXME: Should query this from somewhere, eg for retina displays url = NSURL.fileURLWithPath_(path) dest = Quartz.CGImageDestinationCreateWithURL( url, LaunchServices.kUTTypePNG, # file type 1, # 1 image in file None ) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } # Add the image to the destination, characterizing the image with # the properties dictionary. Quartz.CGImageDestinationAddImage(dest, image, properties) # When all the images (only 1 in this example) are added to the destination, # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest) if __name__ == '__main__': # Capture full screen screenshot("/tmp/testscreenshot_full.png") # Capture region (100x100 box from top-left) region = CG.CGRectMake(0, 0, 100, 100) screenshot("/tmp/testscreenshot_partial.png", region=region) 

Si bien entiendo que este hilo tiene casi cinco años, respondo a esto con la esperanza de que ayude a la gente en el futuro.

Esto es lo que me funcionó, basado en una respuesta en este hilo (el crédito es para ponty ): Tome una captura de pantalla a través de un script de python. [Linux]

https://github.com/ponty/pyscreenshot

Instalar:

 easy_install pyscreenshot 

Ejemplo:

 import pyscreenshot # fullscreen screenshot=pyscreenshot.grab() screenshot.show() # part of the screen screenshot=pyscreenshot.grab(bbox=(10,10,500,500)) screenshot.show() # save to file pyscreenshot.grab_to_file('screenshot.png') 

Pillow ha agregado desde entonces soporte de ImageGrab para macOS!

Sin embargo, no está en v2.9 (a partir de ahora el último) así que acabo de agregar este archivo a mi módulo local.

El código es el siguiente:

 # # The Python Imaging Library # $Id$ # # screen grabber (macOS and Windows only) # # History: # 2001-04-26 fl created # 2001-09-17 fl use builtin driver, if present # 2002-11-19 fl added grabclipboard support # # Copyright (c) 2001-2002 by Secret Labs AB # Copyright (c) 2001-2002 by Fredrik Lundh # # See the README file for information on usage and redistribution. # from . import Image import sys if sys.platform not in ["win32", "darwin"]: raise ImportError("ImageGrab is macOS and Windows only") if sys.platform == "win32": grabber = Image.core.grabscreen elif sys.platform == "darwin": import os import tempfile import subprocess def grab(bbox=None): if sys.platform == "darwin": fh, filepath = tempfile.mkstemp('.png') os.close(fh) subprocess.call(['screencapture', '-x', filepath]) im = Image.open(filepath) im.load() os.unlink(filepath) else: size, data = grabber() im = Image.frombytes( "RGB", size, data, # RGB, 32-bit line padding, origin lower left corner "raw", "BGR", (size[0]*3 + 3) & -4, -1 ) if bbox: im = im.crop(bbox) return im def grabclipboard(): if sys.platform == "darwin": fh, filepath = tempfile.mkstemp('.jpg') os.close(fh) commands = [ "set theFile to (open for access POSIX file \""+filepath+"\" with write permission)", "try", "write (the clipboard as JPEG picture) to theFile", "end try", "close access theFile" ] script = ["osascript"] for command in commands: script += ["-e", command] subprocess.call(script) im = None if os.stat(filepath).st_size != 0: im = Image.open(filepath) im.load() os.unlink(filepath) return im else: debug = 0 # temporary interface data = Image.core.grabclipboard(debug) if isinstance(data, bytes): from . import BmpImagePlugin import io return BmpImagePlugin.DibImageFile(io.BytesIO(data)) return data 

Descubrí que usar webkit2png era la solución más conveniente para mí en OS X.

 brew install webkit2png webkit2png http://stackoverflow.com 
 from subprocess import call import time from time import gmtime, strftime # Take screenshot every 10 seconds and store in the folder where the # code file is present on disk. To stop the script press Cmd+Z/C def take_screen_shot(): # save screen shots where call(["screencapture", "Screenshot" + strftime("%Y-%m-%d %H:%M:%S", gmtime()) + ".jpg"]) def build_screen_shot_base(): while True: take_screen_shot() time.sleep(10) build_screen_shot_base()