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

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

Take a screenshot via a Python script on Linux

我想通过python脚本截取屏幕截图,并毫不干扰地保存它。

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


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

1
2
3
4
5
6
7
8
9
10
11
12
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.webp","png")
    print"Screenshot saved to screenshot.webp."
else:
    print"Unable to get the screenshot."

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


在一堂课中汇编所有答案。
输出PIL图像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/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.webp', 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()


仅出于完整性考虑:
Xlib-但是在捕获整个屏幕时它会比较慢:

1
2
3
4
5
6
7
8
9
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()

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

编辑:
我们可以用C编写函数的核心,然后在ctypes中的python中使用它,这是我一起学习的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#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);
}

然后是python文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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()

这个可以在X11上运行,也许也可以在Windows上运行(请检查一下)。需要PyQt4:

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

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

安装:

1
easy_install pyscreenshot

例:

1
2
3
4
5
6
7
8
9
10
11
12
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.webp')

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

1
2
3
4
5
6
7
8
9
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.webp', wx.BITMAP_TYPE_PNG)


1
2
3
import ImageGrab
img = ImageGrab.grab()
img.save('test.webp','JPEG')

这需要Python Imaging Library


你可以用这个

1
2
import os
os.system("import -window root screen_shot.webp")

我无法在Linux中使用pyscreenshot或scrot截屏,因为pyscreenshot的输出只是黑屏png图像文件。

但是,谢天谢地,在Linux中无需安装任何内容即可获取屏幕截图是另一种非常简单的方法。只需将下面的代码放在您的目录中并使用python demo.py运行

1
2
import os
os.system("gnome-screenshot --file=this_directory.webp")

gnome-screenshot --help也有很多可用的选项

1
2
3
4
5
6
7
8
9
10
11
12
13
Application Options:
  -c, --clipboard                Send the grab directly to the clipboard
  -w, --window                   Grab a window instead of the entire screen
  -a, --area                     Grab an area of the screen instead of the entire screen
  -b, --include-border           Include the window border with the screenshot
  -B, --remove-border            Remove the window border from the screenshot
  -p, --include-pointer          Include the pointer with the screenshot
  -d, --delay=seconds            Take screenshot after specified delay [in seconds]
  -e, --border-effect=effect     Effect to add to the border (shadow, border, vintage or none)
  -i, --interactive              Interactively set options
  -f, --file=filename            Save screenshot directly to this file
  --version                      Print version information and exit
  --display=DISPLAY              X display to use

有点晚,但是没关系,简单的是

1
2
3
4
5
import autopy
import time
time.sleep(2)
b = autopy.bitmap.capture_screen()
b.save("C:/Users/mak/Desktop/m.webp")

这个Autopy有一个python包

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


从这个线程:

1
2
 import os
 os.system("import -window root temp.webp")

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

适用于python 3(应该适用于python 2,但我尚未对其进行测试)和PyQt5。

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

1
2
3
4
5
from PyQt5.QtWidgets import QApplication
app = QApplication([])
screen = app.primaryScreen()
screenshot = screen.grabWindow(QApplication.desktop().winId())
screenshot.save('/tmp/screenshot.webp')

尝试一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/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 +=".webp"

    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."


推荐阅读

    linux脚本多个命令?

    linux脚本多个命令?,系统,工作,标准,服务,命令,软件,管理,连续,电脑,设备,lin

    linux命令支持通配符?

    linux命令支持通配符?,工具,系统,命令,灵活,较大,名称,名字,环境,数字,文件,L

    linux脚本注释命令?

    linux脚本注释命令?,代码,系统,工作,名称,地方,脚本,命令,信息,状态,简介,lin

    脚本运行linux命令?

    脚本运行linux命令?,系统,环境,工具,工作,位置,底部,代码,发行,官网,终端,lin

    linux命令下写脚本?

    linux命令下写脚本?,服务,系统,环境,代码,名称,命令,脚本,发行,在线,情况,三

    linux把命令变成脚本?

    linux把命令变成脚本?,系统,环境,工作,脚本,命令,信息,基础,代码,文件,变量,

    脚本调用linux命令?

    脚本调用linux命令?,代码,系统,工作,底部,脚本,位置,环境,行用,官网,标准,typ

    linux支持管道的命令?

    linux支持管道的命令?,通信,标准,系统,信息,地方,数据,管道,环境,设备,工具,L

    linux脚本命令输信息?

    linux脚本命令输信息?,系统,信息,代码,脚本,数据,工具,发行,命令,变量,文件,l

    linux上启动脚本命令?

    linux上启动脚本命令?,服务,状态,系统,代码,脚本,工作,周期性,命令,文件,方

    linux下编写脚本命令?

    linux下编写脚本命令?,代码,时间,工具,标准,系统,实战,平台,最新,网站,文件,l

    linux定时器脚本命令?

    linux定时器脚本命令?,系统,代码,时间,工具,工作,定期,周期性,异常,任务,脚

    linux停止脚本命令行?

    linux停止脚本命令行?,系统,工作,平台,命令,基础,第一,环境,信息,终端,程序,

    linux命令运行脚本?

    linux命令运行脚本?,代码,系统,工作,设计,状态,命令,脚本,文件,目录,终端,运

    linux脚本赋权限命令?

    linux脚本赋权限命令?,系统,档案,工作,命令,工具,脚本,权限,文件,程序,文件

    linux关闭脚本命令?

    linux关闭脚本命令?,系统,服务,状态,命令,档案,暂停,软件,工具,数据,电脑,lin

    linux激活脚本命令?

    linux激活脚本命令?,系统,信息,环境,脚本,命令,代码,服务,工具,标准,官网,如

    linux循环命令脚本?

    linux循环命令脚本?,代码,系统,增长,工具,官网,项目,流程,数据,数字,底部,lin

    执行脚本命令linux?

    执行脚本命令linux?,工作,脚本,服务,命令,文件,方法,权限,目录,用户,可能会,L

    停止linux脚本命令行?

    停止linux脚本命令行?,状态,电脑,命令,传播,检测,终端,模式,指令,文件,进程,l