在 Linux 上通过 Python 脚本截取屏幕截图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/69645/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:25:21  来源:igfitidea点击:

Take a screenshot via a Python script on Linux

pythonlinuxscreenshot

提问by skyronic

I want to take a screenshot via a python script and unobtrusively save it.

我想通过python脚本截取屏幕截图并不显眼地保存它。

I'm only interested in the Linux solution, and should support any X based environment.

我只对 Linux 解决方案感兴趣,应该支持任何基于 X 的环境。

采纳答案by Rusty

This works without having to use scrot or ImageMagick.

这无需使用 scrot 或 ImageMagick 即可工作。

import gtk.gdk

w = gtk.gdk.get_default_root_window()
sz = w.get_size()
print "The size of the window is %d x %d" % sz
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
if (pb != None):
    pb.save("screenshot.png","png")
    print "Screenshot saved to screenshot.png."
else:
    print "Unable to get the screenshot."

Borrowed from http://ubuntuforums.org/showpost.php?p=2681009&postcount=5

借自http://ubuntuforums.org/showpost.php?p=2681009&postcount=5

回答by Slava V

import ImageGrab
img = ImageGrab.grab()
img.save('test.jpg','JPEG')

this requires Python Imaging Library

这需要 Python 图像库

回答by Juliano

This one works on X11, and perhaps on Windows too (someone, please check). Needs PyQt4:

这个适用于 X11,也许也适用于 Windows(有人,请检查)。需要PyQt4

import sys
from PyQt4.QtGui import QPixmap, QApplication
app = QApplication(sys.argv)
QPixmap.grabWindow(QApplication.desktop().winId()).save('test.png', 'png')

回答by Snowball

Cross platform solution using wxPython:

使用wxPython 的跨平台解决方案:

import wx
wx.App()  # Need to create an App instance before doing anything
screen = wx.ScreenDC()
size = screen.GetSize()
bmp = wx.EmptyBitmap(size[0], size[1])
mem = wx.MemoryDC(bmp)
mem.Blit(0, 0, size[0], size[1], screen, 0, 0)
del mem  # Release bitmap
bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG)

回答by Alex Snet

Compile all answers in one class. Outputs PIL image.

将所有答案汇总在一节课中。输出 PIL 图像。

#!/usr/bin/env python
# encoding: utf-8
"""
screengrab.py

Created by Alex Snet on 2011-10-10.
Copyright (c) 2011 CodeTeam. All rights reserved.
"""

import sys
import os

import Image


class screengrab:
    def __init__(self):
        try:
            import gtk
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByGtk

        try:
            import PyQt4
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByQt

        try:
            import wx
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByWx

        try:
            import ImageGrab
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByPIL


    def getScreenByGtk(self):
        import gtk.gdk      
        w = gtk.gdk.get_default_root_window()
        sz = w.get_size()
        pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
        pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
        if pb is None:
            return False
        else:
            width,height = pb.get_width(),pb.get_height()
            return Image.fromstring("RGB",(width,height),pb.get_pixels() )

    def getScreenByQt(self):
        from PyQt4.QtGui import QPixmap, QApplication
        from PyQt4.Qt import QBuffer, QIODevice
        import StringIO
        app = QApplication(sys.argv)
        buffer = QBuffer()
        buffer.open(QIODevice.ReadWrite)
        QPixmap.grabWindow(QApplication.desktop().winId()).save(buffer, 'png')
        strio = StringIO.StringIO()
        strio.write(buffer.data())
        buffer.close()
        del app
        strio.seek(0)
        return Image.open(strio)

    def getScreenByPIL(self):
        import ImageGrab
        img = ImageGrab.grab()
        return img

    def getScreenByWx(self):
        import wx
        wx.App()  # Need to create an App instance before doing anything
        screen = wx.ScreenDC()
        size = screen.GetSize()
        bmp = wx.EmptyBitmap(size[0], size[1])
        mem = wx.MemoryDC(bmp)
        mem.Blit(0, 0, size[0], size[1], screen, 0, 0)
        del mem  # Release bitmap
        #bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG)
        myWxImage = wx.ImageFromBitmap( myBitmap )
        PilImage = Image.new( 'RGB', (myWxImage.GetWidth(), myWxImage.GetHeight()) )
        PilImage.fromstring( myWxImage.GetData() )
        return PilImage

if __name__ == '__main__':
    s = screengrab()
    screen = s.screen()
    screen.show()

回答by ponty

I have a wrapper project (pyscreenshot) for scrot, imagemagick, pyqt, wx and pygtk. If you have one of them, you can use it. All solutions are included from this discussion.

我有一个用于 scrot、imagemagick、pyqt、wx 和 pygtk的包装项目 ( pyscreenshot)。如果您有其中之一,则可以使用它。所有解决方案都包含在此讨论中。

Install:

安装:

easy_install pyscreenshot

Example:

例子:

import pyscreenshot as ImageGrab

# fullscreen
im=ImageGrab.grab()
im.show()

# part of the screen
im=ImageGrab.grab(bbox=(10,10,500,500))
im.show()

# to file
ImageGrab.grab_to_file('im.png')

回答by JHolta

Just for completeness: Xlib - But it's somewhat slow when capturing the whole screen:

只是为了完整性:Xlib - 但是在捕获整个屏幕时它有点慢:

from Xlib import display, X
import Image #PIL

W,H = 200,200
dsp = display.Display()
root = dsp.screen().root
raw = root.get_image(0, 0, W,H, X.ZPixmap, 0xffffffff)
image = Image.fromstring("RGB", (W, H), raw.data, "raw", "BGRX")
image.show()

One could try to trow some types in the bottleneck-files in PyXlib, and then compile it using Cython. That could increase the speed a bit.

可以尝试在 PyXlib 的瓶颈文件中添加一些类型,然后使用 Cython 编译它。这样可以稍微提高速度。



Edit:We can write the core of the function in C, and then use it in python from ctypes, here is something I hacked together:

编辑:我们可以在 C 中编写函数的核心,然后从 ctypes 在 python 中使用它,这是我一起破解的东西:

#include <stdio.h>
#include <X11/X.h>
#include <X11/Xlib.h>
//Compile hint: gcc -shared -O3 -lX11 -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c

void getScreen(const int, const int, const int, const int, unsigned char *);
void getScreen(const int xx,const int yy,const int W, const int H, /*out*/ unsigned char * data) 
{
   Display *display = XOpenDisplay(NULL);
   Window root = DefaultRootWindow(display);

   XImage *image = XGetImage(display,root, xx,yy, W,H, AllPlanes, ZPixmap);

   unsigned long red_mask   = image->red_mask;
   unsigned long green_mask = image->green_mask;
   unsigned long blue_mask  = image->blue_mask;
   int x, y;
   int ii = 0;
   for (y = 0; y < H; y++) {
       for (x = 0; x < W; x++) {
         unsigned long pixel = XGetPixel(image,x,y);
         unsigned char blue  = (pixel & blue_mask);
         unsigned char green = (pixel & green_mask) >> 8;
         unsigned char red   = (pixel & red_mask) >> 16;

         data[ii + 2] = blue;
         data[ii + 1] = green;
         data[ii + 0] = red;
         ii += 3;
      }
   }
   XDestroyImage(image);
   XDestroyWindow(display, root);
   XCloseDisplay(display);
}

And then the python-file:

然后是python文件:

import ctypes
import os
from PIL import Image

LibName = 'prtscn.so'
AbsLibPath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + LibName
grab = ctypes.CDLL(AbsLibPath)

def grab_screen(x1,y1,x2,y2):
    w, h = x2-x1, y2-y1
    size = w * h
    objlength = size * 3

    grab.getScreen.argtypes = []
    result = (ctypes.c_ubyte*objlength)()

    grab.getScreen(x1,y1, w, h, result)
    return Image.frombuffer('RGB', (w, h), result, 'raw', 'RGB', 0, 1)

if __name__ == '__main__':
  im = grab_screen(0,0,1440,900)
  im.show()

回答by Anand

Try it:

尝试一下:

#!/usr/bin/python

import gtk.gdk
import time
import random
import socket
import fcntl
import struct
import getpass
import os
import paramiko     

while 1:
    # generate a random time between 120 and 300 sec
    random_time = random.randrange(20,25)
    # wait between 120 and 300 seconds (or between 2 and 5 minutes) 

    print "Next picture in: %.2f minutes" % (float(random_time) / 60)

    time.sleep(random_time)
    w = gtk.gdk.get_default_root_window()   
    sz = w.get_size()
    print "The size of the window is %d x %d" % sz
    pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
    pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
    ts = time.asctime( time.localtime(time.time()) )
    date = time.strftime("%d-%m-%Y")
    timer = time.strftime("%I:%M:%S%p")
    filename = timer
    filename += ".png"

    if (pb != None):
        username = getpass.getuser() #Get username
        newpath = r'screenshots/'+username+'/'+date #screenshot save path
        if not os.path.exists(newpath): os.makedirs(newpath)
        saveas = os.path.join(newpath,filename)
        print saveas
        pb.save(saveas,"png")
    else:
        print "Unable to get the screenshot."

回答by ouille

There is a python package for this Autopy

这个Autopy有一个 python 包

The bitmap module can to screen grabbing (bitmap.capture_screen) It is multiplateform (Windows, Linux, Osx).

位图模块可以进行屏幕抓取(bitmap.capture_screen) 是多平台的(Windows、Linux、Osx)。

回答by rominf

It's an old question. I would like to answer it using new tools.

这是一个老问题。我想使用新工具来回答它。

Works with python 3 (should work with python 2, but I haven't test it) and PyQt5.

适用于 python 3(应该适用于 python 2,但我还没有测试过)和 PyQt5。

Minimal working example. Copy it to the python shell and get the result.

最小的工作示例。将其复制到python shell并获取结果。

from PyQt5.QtWidgets import QApplication
app = QApplication([])
screen = app.primaryScreen()
screenshot = screen.grabWindow(QApplication.desktop().winId())
screenshot.save('/tmp/screenshot.png')