Quiero tomar una captura de pantalla a través de una secuencia de comandos de Python y guardarla discretamente.
Solo estoy interesado en la solución Linux y debería admitir cualquier entorno basado en X.
                    
                        python
                                linux
                                screenshot
                                
                    
                    
                        skyronic
fuente
                
                fuente

Respuestas:
Esto funciona sin tener que usar scrot o 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."Tomado de http://ubuntuforums.org/showpost.php?p=2681009&postcount=5
fuente
Recopile todas las respuestas en una clase. Emite una imagen 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()fuente
getScreenByWxmétodo fallawx._core.PyNoAppError: The wx.App object must be created first!. Curiosamente, el código funciona bien si lo ingresa línea por línea en el shell de Python, pero falla en un script.getScreenByWxdebes a) reemplazarmyBitmapporbmpyb) guardarwx.App()en una variable. EngetScreenByGtkreemplazo(pb != None)depb is None. Y no use Qt, así que, no puede crear dos vecesQApplication, su aplicación se bloqueará al intentar crearla por segunda vez.Solo para completar: Xlib, pero es algo lento cuando se captura toda la pantalla:
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()Se podría intentar introducir algunos tipos en los archivos de cuello de botella en PyXlib y luego compilarlos usando Cython. Eso podría aumentar un poco la velocidad.
Editar: Podemos escribir el núcleo de la función en C y luego usarlo en python desde ctypes, aquí hay algo que pirateé juntos:
#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); }Y luego el archivo 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()fuente
#include <X11/Xutil.h>hacerlo en lugar de hacerlo#include <X11/Xlib.h>. También para la compilación, que tenía que mover-lX11a finales de esta manera:gcc -shared -O3 -Wall -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c -lX11.Este funciona en X11, y quizás también en Windows (alguien, por favor verifique). Necesita PyQt4 :
import sys from PyQt4.QtGui import QPixmap, QApplication app = QApplication(sys.argv) QPixmap.grabWindow(QApplication.desktop().winId()).save('test.png', 'png')fuente
Tengo un proyecto de envoltura ( captura de pantalla ) para scrot, imagemagick, pyqt, wx y pygtk. Si tiene uno de ellos, puede usarlo. Todas las soluciones se incluyen en esta discusión.
Instalar en pc:
Ejemplo:
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')fuente
pyscreenshot.tempexport.RunProgError: No protocol specified giblib error: Can't open X display. It *is* running, yeah?" timeout_happened=False>Solución multiplataforma usando 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)fuente
import ImageGrab img = ImageGrab.grab() img.save('test.jpg','JPEG')esto requiere la biblioteca de imágenes de Python
fuente
Puedes usar esto
import os os.system("import -window root screen_shot.png")fuente
Un poco tarde, pero no importa, es fácil.
import autopy import time time.sleep(2) b = autopy.bitmap.capture_screen() b.save("C:/Users/mak/Desktop/m.png")fuente
No pude tomar una captura de pantalla en Linux con pyscreenshot o scrot porque la salida de
pyscreenshotera solo un archivo de imagen png de pantalla negra.pero gracias a Dios había otra forma muy fácil de hacer capturas de pantalla en Linux sin instalar nada. simplemente ponga el código debajo en su directorio y ejecútelo con
python demo.pyimport os os.system("gnome-screenshot --file=this_directory.png")también hay muchas opciones disponibles para
gnome-screenshot --helpApplication 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 usefuente
Hay un paquete de Python para este Autopy
El módulo de mapa de bits puede capturar pantalla (bitmap.capture_screen) Es multiplataforma (Windows, Linux, Osx).
fuente
De este hilo :
import os os.system("import -window root temp.png")fuente
para ubuntu este trabajo para mí, puede tomar una captura de pantalla de la ventana de selección con esto:
import gi gi.require_version('Gtk', '3.0') from gi.repository import Gdk from gi.repository import GdkPixbuf import numpy as np from Xlib.display import Display #define the window name window_name = 'Spotify' #define xid of your select 'window' def locate_window(stack,window): disp = Display() NET_WM_NAME = disp.intern_atom('_NET_WM_NAME') WM_NAME = disp.intern_atom('WM_NAME') name= [] for i, w in enumerate(stack): win_id =w.get_xid() window_obj = disp.create_resource_object('window', win_id) for atom in (NET_WM_NAME, WM_NAME): window_name=window_obj.get_full_property(atom, 0) name.append(window_name.value) for l in range(len(stack)): if(name[2*l]==window): return stack[l] window = Gdk.get_default_root_window() screen = window.get_screen() stack = screen.get_window_stack() myselectwindow = locate_window(stack,window_name) img_pixbuf = Gdk.pixbuf_get_from_window(myselectwindow,*myselectwindow.get_geometry())para transformar pixbuf en una matriz
def pixbuf_to_array(p): w,h,c,r=(p.get_width(), p.get_height(), p.get_n_channels(), p.get_rowstride()) assert p.get_colorspace() == GdkPixbuf.Colorspace.RGB assert p.get_bits_per_sample() == 8 if p.get_has_alpha(): assert c == 4 else: assert c == 3 assert r >= w * c a=np.frombuffer(p.get_pixels(),dtype=np.uint8) if a.shape[0] == w*c*h: return a.reshape( (h, w, c) ) else: b=np.zeros((h,w*c),'uint8') for j in range(h): b[j,:]=a[r*j:r*j+w*c] return b.reshape( (h, w, c) ) beauty_print = pixbuf_to_array(img_pixbuf)fuente
Es una vieja pregunta. Me gustaría responderla usando nuevas herramientas.
Funciona con python 3 (debería funcionar con python 2, pero no lo he probado) y PyQt5.
Ejemplo de trabajo mínimo. Cópielo en el shell de Python y obtenga el resultado.
from PyQt5.QtWidgets import QApplication app = QApplication([]) screen = app.primaryScreen() screenshot = screen.grabWindow(QApplication.desktop().winId()) screenshot.save('/tmp/screenshot.png')fuente
Intentalo:
#!/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."fuente
whilebucle que nunca sale (y usa en1lugar deTrue), tiene enif (pb != None):lugar de soloif pb:, tiene algunas cadenas sin procesar sin sentido.