在Mac OS X上使用Python截取屏幕截图

时间:2010-12-24 06:52:56

标签: python macos screenshot

来自PIL的ImageGrab本来是理想的。我正在寻找类似的功能,特别是能够定义屏幕截图的边界框。我一直在寻找一个可以在Mac OS X上运行的库,但没有任何运气。我也找不到任何示例代码(也许是pyobjc?)。

7 个答案:

答案 0 :(得分:16)

虽然不完全符合您的要求,但您可以使用:

os.system("screencapture screen.png")

然后使用Image模块打开该图像。我确信存在更好的解决方案。

答案 1 :(得分:10)

以下是如何使用PyObjC捕获和保存屏幕截图,基于my answer here

您可以捕获整个屏幕,或指定要捕获的区域。如果您不需要这样做,我建议您只需调用screencapture命令(更多功能,更强大,更快 - 仅初始PyObjC导入可能需要大约一秒钟)

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, e.g 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)

答案 2 :(得分:6)

虽然我确实知道这个帖子已接近五年了,但我正在回答这个问题,希望它能在未来帮助人们。

根据此主题中的答案(信用转到ponty),以下是对我有用的内容:Take a screenshot via a python script. [Linux]

https://github.com/ponty/pyscreenshot

安装:

easy_install pyscreenshot

示例:

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')

答案 3 :(得分:1)

Pillow已经为macOS添加了ImageGrab支持!

然而,它不在v2.9中(截至目前为止最新版本)所以我只是将此文件添加到我的本地模块中。

代码如下:

#
# 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

答案 4 :(得分:0)

我发现在OS X上使用webkit2png对我来说是最方便的解决方案。

brew install webkit2png
webkit2png http://stackoverflow.com

答案 5 :(得分:0)

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()

答案 6 :(得分:0)

enter image description here

CTRL + Shift + 3

CTRL + Shift + 4

在Mac屏幕截图中