लिनक्स पर एक पायथन स्क्रिप्ट के माध्यम से स्क्रीनशॉट लें


81

मैं एक अजगर स्क्रिप्ट के माध्यम से स्क्रीनशॉट लेना चाहता हूं और विनीत रूप से इसे सहेजना चाहता हूं।

मुझे केवल Linux समाधान में दिलचस्पी है, और किसी भी X आधारित वातावरण का समर्थन करना चाहिए।


किसी भी कारण से आप स्क्रोट का उपयोग नहीं कर सकते हैं ?
मार्क

मैं नीचे दिए गए तरीकों के प्रदर्शन की जांच करने के लिए उत्सुक हूं।
जॉन्ग जूल

4
नया लिंक: manpages.ubuntu.com/manpages/karmic/man1/scrot.1.html (@ArtOfWarfare)
Mark

@ मर्क -: - / अफसोस की बात है कि स्क्रोट ओएस एक्स के साथ नहीं आता है (मुझे पता है, यह एक लिनक्स सवाल था। बस सामान्य रूप से लिनक्स पर जो भी लागू होता है वह ओएस एक्स
वर्बेटिम

आह ठीक है, अच्छी तरह से यह OS X पर screencapture
मार्क

जवाबों:


65

यह स्क्रोट या इमेजमैजिक का उपयोग किए बिना काम करता है।

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

से उधार http://ubuntuforums.org/showpost.php?p=2681009&postcount=5


यह जीयूआई आधारित अनुप्रयोग में ग्लेड और जल्दी से काम नहीं करता है, क्या आप इस कोड में सुधार कर सकते हैं।
सुबोध गुलालके

जब मैं इस कोड को निष्पादित करता हूं (वर्चुअलबॉक्स में लिनक्स मिंट 16 का उपयोग करके) तो परिणामस्वरूप छवि पूरी तरह से काली है। क्या आपके पास कोई विचार है क्यों?
बाबा

कभी-कभी रंगों की एन्कोडिंग बंद होती है। यह काफी कष्टप्रद है। देखें कि क्या github.com/JDong820/neobot/blob/master/Linux/Robot/screen.py आपके लिए कोई मददगार है; get_rowstride पर कॉल को नोटिस करें।
17

48

एक कक्षा में सभी उत्तरों को संकलित करें। पीआईएल छवि आउटपुट।

#!/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()

मुझे नहीं पता कि इस पोस्ट के बाद से wxWidgets में कोई बदलाव हुआ है या नहीं, लेकिन यह getScreenByWxविधि विफल है wx._core.PyNoAppError: The wx.App object must be created first!। मजेदार रूप से पर्याप्त है, कोड ठीक काम करता है यदि आप इसे लाइन द्वारा अजगर शेल में लाइन में प्रवेश कर रहे हैं, लेकिन एक स्क्रिप्ट में यह विफल रहता है।
CadentOrange

आपको अपने कोड का परीक्षण करना चाहिए! या, आपका नहीं, यदि आप इसे प्रकाशित कर रहे हैं ... getScreenByWxआप में एक) myBitmapद्वारा प्रतिस्थापित किया जाना चाहिए bmpऔर ख) wx.App()एक चर में सहेजें । को getScreenByGtkप्रतिस्थापित (pb != None)करने में pb is None। और Qt का उपयोग न करें - आप दो बार नहीं बना सकते हैं QApplication- आपका ऐप दूसरी बार बनाने की कोशिश में दुर्घटनाग्रस्त हो जाएगा।
जूरी

41

बस पूर्णता के लिए: 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()

पाइक्लिब में अड़चन-फाइलों में कुछ प्रकारों को फेंकने की कोशिश कर सकता है, और फिर साइथन का उपयोग करके इसे संकलित कर सकता है। जिससे स्पीड थोड़ी बढ़ सके।


संपादित करें: हम C में फ़ंक्शन का मूल लिख सकते हैं, और फिर इसे ctypes से अजगर में उपयोग कर सकते हैं, यहाँ कुछ ऐसा है जिसे मैंने एक साथ हैक किया है:

#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);
}

और फिर अजगर-फाइल:

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

3
यह सोने के लायक है, यदि अन्य उत्तरों की तुलना में कम से कम वोट नहीं। ठोस काम और एक देशी भी! चीयर्स!
Torxed

1
उन लोगों के लिए जो तेजी से रास्ता ढूंढ रहे हैं: यह दृष्टिकोण आकार के एक चित्र के लिए औसतन
डिकैप्रियो

1
@ जोल्टा, क्या आप कैप्चर की गई छवि की गुणवत्ता को बदलने का एक तरीका जानते हैं? (और भी अधिक तेजी लाने के लिए)
डिकैप्रियो

1
नहीं। वर्तमान में यह सिर्फ डेस्कटॉप छवि को कॉपी कर रहा है, जैसा कि छवि के किसी भी परिवर्तन से ओवरहेड हो जाएगा। तो अपने डेस्कटॉप की वास्तविक गुणवत्ता को कम किए बिना, आप उस विचार पर भाग्य से बाहर हैं। वैसे भी, वर्तमान ओवरहेड चीजों के पायथन छोर पर संभवतया है, जहां हम एक बफर को पूर्व-आवंटित करते हैं (प्रोब में c किया जा सकता है), और दूसरा धीमा हिस्सा जहां पीआईएल इस बफर में पढ़ता है, उन दोनों को अनुकूलित किया जा सकता है, और। शायद चीजों के सी अंत पर रखा।
झोलता

6
यह बहुत अच्छा काम करता है, लेकिन मुझे #include <X11/Xutil.h>इसके बजाय करना पड़ा #include <X11/Xlib.h>। संकलन के लिए भी, मुझे -lX11इस तरह अंत में जाना था gcc -shared -O3 -Wall -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c -lX11:।
जोश

18

यह एक X11 पर काम करता है, और शायद विंडोज पर भी (कोई, कृपया जाँच करें)। आवश्यकताएं PyQt4 :

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

2
कृपया PyQt की लाइसेंसिंग पर ध्यान दें, जो Python और Qt की तुलना में अधिक प्रतिबंधात्मक है। riverbankcomputing.co.uk/software/pyqt/license
user120242

यह एकमात्र समाधान है जो मेरे लिनक्स इंस्टॉलेशन "आउट-ऑफ-द-बॉक्स" पर चलता है। मुझे पता नहीं क्यों, लेकिन मेरे पास हर जगह PyQt4 है, जबकि PyWX, PyGtk, ImageGrab की कमी है। - धन्यवाद :)।
ग्रेज़गोरज़ विएर्ज़ोवेकी

कोड ने सिर्फ काम किया (विंडोज 7 x64 पर - पायथन 2.7.5; पायथनोइस डिस्ट्रब्यूशन)। जेपीईजी भी उपलब्ध (जैसे ... .Save ('d: /test.jpg', 'jpeg'))
मोहम्मद फकीह

15

मेरे पास एक रैपर प्रोजेक्ट ( pyscreenshot ) है जो scrot, imagemagick, pyqt, wx और pygtk के लिए है। यदि आपके पास उनमें से एक है, तो आप इसका उपयोग कर सकते हैं। इस चर्चा से सभी समाधान शामिल हैं।

इंस्टॉल:

easy_install pyscreenshot

उदाहरण:

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

ImportError: नाम आयात नहीं कर सकते gtkpixbuf
tommy.carstensen

यह मुझे यह त्रुटि दे रहा है:pyscreenshot.tempexport.RunProgError: No protocol specified giblib error: Can't open X display. It *is* running, yeah?" timeout_happened=False>
जसर ओरियन

9

क्रॉस प्लेटफॉर्म सॉल्यूशन का उपयोग करते हुए 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)

अजगर कोड के भीतर टिप्पणी, स्पष्टीकरण और संदर्भ के साथ संदर्भ। blog.pythonlibrary.org/2010/04/16/... या blog.pythonlibrary.org/2010/04/16/...
नागरिक


5

आप इसका उपयोग कर सकते हैं

import os
os.system("import -window root screen_shot.png")

यह एक अच्छा तरीका है एक बार जब आप एक पृष्ठभूमि कार्यक्रम से छवि प्राप्त कर सकते हैं, लेकिन यह जानना अच्छा है कि यदि कार्यक्रम केंद्रित है तो यह एक अपवाद लौटाएगा।
लुकास आराजो

3

थोड़ा देर से लेकिन आसान कोई नहीं है

import autopy
import time
time.sleep(2)
b = autopy.bitmap.capture_screen()
b.save("C:/Users/mak/Desktop/m.png")

3

मैं लिनक्स में pyscreenshot या scrot के साथ स्क्रीनशॉट नहीं ले सका क्योंकि आउटपुट pyscreenshotसिर्फ एक काली स्क्रीन png छवि फ़ाइल थी।

लेकिन भगवान का शुक्र है कि लिनक्स में स्क्रीनशॉट लेने के लिए कुछ भी स्थापित किए बिना एक और बहुत आसान तरीका था। बस अपनी निर्देशिका में नीचे कोड डाल दिया और साथ चलाpython demo.py

import os
os.system("gnome-screenshot --file=this_directory.png")

इसके लिए भी कई उपलब्ध विकल्प हैं gnome-screenshot --help

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

2

इस Autopy के लिए एक अजगर पैकेज है

बिटमैप मॉड्यूल हथियाने को स्क्रीन कर सकता है (बिटमैप.कैपचर_स्क्रीन) यह गुणक है (विंडोज, लिनक्स, ओएक्सएक्स)।



1

मेरे लिए यह काम ubuntu के लिए, आप इसके साथ चुनिंदा विंडो का स्क्रीनशॉट ले सकते हैं:

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

Pixbuf को सरणी में बदलना

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)

0

यह एक पुराना सवाल है। मैं नए उपकरणों का उपयोग करके इसका उत्तर देना चाहूंगा।

अजगर 3 के साथ काम करता है (अजगर 2 के साथ काम करना चाहिए, लेकिन मैंने इसे परीक्षण नहीं किया है) और PyQt5।

न्यूनतम काम करने का उदाहरण। इसे अजगर शेल में कॉपी करें और परिणाम प्राप्त करें।

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

क्या आपको इस फ़ंक्शन को पूरा करने के लिए औसत समय मिला है? अगर इसके लायक है तो बस ब्याज
डिकैप्रियो

1
@ मार्नेनी 300 एमएस (पूर्ण कोड के लिए), 165 एमएस (कोड की अंतिम तीन लाइनें)।
रोमिंथ

-3

कोशिश करो:

#!/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."

3
यह क्या बकवास है? आधा आयात बेकार हैं, एक whileलूप है जो कभी बाहर नहीं निकलता (और 1इसके बजाय उपयोग करता है True), if (pb != None):बस के बजाय है if pb:, कुछ बेकार तार हैं।
ArtOfWarfare
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.