2009-07-28 22 views
39

Lo que quiero lograr es obtener una captura de pantalla del sitio web desde cualquier sitio web en python.¿Cómo puedo tomar una captura de pantalla/imagen de un sitio web usando Python?

Env: Linux

+4

Una búsqueda rápida en el sitio muestra muchos, muchos casi duplicados de esto. Este es un buen comienzo: http://stackoverflow.com/questions/713938/how-can-i-generate-a-screenshot-of-a-webpage-using-a-server-side-script – Shog9

+0

Shog9: ¡¡¡Gracias !! su enlace tiene algunos ... lo comprobará. –

+0

Shog9: ¿por qué no lo agrega como respuesta? por lo que puede darte puntos. –

Respuesta

8

En Mac, hay webkit2png y en Linux + KDE, puede usar khtml2png. Probé con el anterior y funciona bastante bien, y escuché que este último se usó.

Recientemente me encontré con QtWebKit que dice ser plataforma cruzada (Qt rodó WebKit en su biblioteca, supongo). Pero nunca lo intenté, así que no puedo contarte mucho más.

Los enlaces de QtWebKit muestran cómo acceder desde Python. Debería poder al menos usar un subproceso para hacer lo mismo con los demás.

+0

khtml2png está desactualizado de acuerdo con el sitio web, [python-webkit2png] (https://github.com/adamn/python-webkit2png/) es recomendado por ellos. – sebix

0

Usted no menciona qué entorno se está ejecutando en el que hace una gran diferencia, ya que no es un navegador web de Python puro, que es capaz de renderizar HTML.

Pero si está usando una Mac, he usado webkit2png con gran éxito. De lo contrario, como han señalado otros, hay muchas opciones.

5

No puedo comentar la respuesta de ars, pero en realidad obtuve Roland Tapken's code ejecutándose con QtWebkit y funciona bastante bien.

Solo quería confirmar que lo que Roland publica en su blog funciona muy bien en Ubuntu. Nuestra versión de producción terminó sin usar nada de lo que escribió, pero estamos utilizando las vinculaciones PyQt/QtWebKit con mucho éxito.

+0

Cool. Creo que esa es la lib que intentaré la próxima vez que necesite algo como esto. – ars

+0

Terminamos poniendo un servidor RabbitMQ encima y construyendo un código para controlar los servidores Xvfb y los procesos que se ejecutan en ellos para pseudo-enhebrar las capturas de pantalla que se están construyendo. Funciona decentemente rápido con una cantidad aceptable de uso de memoria. – aezell

38

Aquí es una solución simple que utiliza WebKit: http://webscraping.com/blog/Webpage-screenshots-with-webkit/

import sys 
import time 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
from PyQt4.QtWebKit import * 

class Screenshot(QWebView): 
    def __init__(self): 
     self.app = QApplication(sys.argv) 
     QWebView.__init__(self) 
     self._loaded = False 
     self.loadFinished.connect(self._loadFinished) 

    def capture(self, url, output_file): 
     self.load(QUrl(url)) 
     self.wait_load() 
     # set to webpage size 
     frame = self.page().mainFrame() 
     self.page().setViewportSize(frame.contentsSize()) 
     # render image 
     image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) 
     painter = QPainter(image) 
     frame.render(painter) 
     painter.end() 
     print 'saving', output_file 
     image.save(output_file) 

    def wait_load(self, delay=0): 
     # process app events until page loaded 
     while not self._loaded: 
      self.app.processEvents() 
      time.sleep(delay) 
     self._loaded = False 

    def _loadFinished(self, result): 
     self._loaded = True 

s = Screenshot() 
s.capture('http://webscraping.com', 'website.png') 
s.capture('http://webscraping.com/blog', 'blog.png') 
+0

Funciona bien, gracias. Sin embargo, funciona de manera confiable solo si se ejecuta desde la línea de comando. En un proyecto django, uno usaría subprocess.Popen() –

+1

funciona bien desde dentro de un marco web python. Sin embargo, se necesita un poco de esfuerzo para que Webkit funcione sin cabeza. – hoju

+2

¿Alguien experimentó problemas al usar el método de @hoju? No funciona en todas las páginas web ... – Hiatus

33

Aquí está mi solución por el acaparamiento de ayuda de varias fuentes. Toma una captura de pantalla completa de la página web y la cosecha (opcional) y también genera una miniatura desde la imagen recortada. Los siguientes son los requisitos:

Requisitos:

  1. Instalar NodeJS
  2. Usando gestor de paquetes de entrada Instalación PhantomJS: npm -g install phantomjs
  3. Instalar selenio (en su virtualenv, si está utilizando eso)
  4. Instalar imageMagick
  5. Agregar phantomjs a la ruta del sistema (en windows)

import os 
from subprocess import Popen, PIPE 
from selenium import webdriver 

abspath = lambda *p: os.path.abspath(os.path.join(*p)) 
ROOT = abspath(os.path.dirname(__file__)) 


def execute_command(command): 
    result = Popen(command, shell=True, stdout=PIPE).stdout.read() 
    if len(result) > 0 and not result.isspace(): 
     raise Exception(result) 


def do_screen_capturing(url, screen_path, width, height): 
    print "Capturing screen.." 
    driver = webdriver.PhantomJS() 
    # it save service log file in same directory 
    # if you want to have log file stored else where 
    # initialize the webdriver.PhantomJS() as 
    # driver = webdriver.PhantomJS(service_log_path='/var/log/phantomjs/ghostdriver.log') 
    driver.set_script_timeout(30) 
    if width and height: 
     driver.set_window_size(width, height) 
    driver.get(url) 
    driver.save_screenshot(screen_path) 


def do_crop(params): 
    print "Croping captured image.." 
    command = [ 
     'convert', 
     params['screen_path'], 
     '-crop', '%sx%s+0+0' % (params['width'], params['height']), 
     params['crop_path'] 
    ] 
    execute_command(' '.join(command)) 


def do_thumbnail(params): 
    print "Generating thumbnail from croped captured image.." 
    command = [ 
     'convert', 
     params['crop_path'], 
     '-filter', 'Lanczos', 
     '-thumbnail', '%sx%s' % (params['width'], params['height']), 
     params['thumbnail_path'] 
    ] 
    execute_command(' '.join(command)) 


def get_screen_shot(**kwargs): 
    url = kwargs['url'] 
    width = int(kwargs.get('width', 1024)) # screen width to capture 
    height = int(kwargs.get('height', 768)) # screen height to capture 
    filename = kwargs.get('filename', 'screen.png') # file name e.g. screen.png 
    path = kwargs.get('path', ROOT) # directory path to store screen 

    crop = kwargs.get('crop', False) # crop the captured screen 
    crop_width = int(kwargs.get('crop_width', width)) # the width of crop screen 
    crop_height = int(kwargs.get('crop_height', height)) # the height of crop screen 
    crop_replace = kwargs.get('crop_replace', False) # does crop image replace original screen capture? 

    thumbnail = kwargs.get('thumbnail', False) # generate thumbnail from screen, requires crop=True 
    thumbnail_width = int(kwargs.get('thumbnail_width', width)) # the width of thumbnail 
    thumbnail_height = int(kwargs.get('thumbnail_height', height)) # the height of thumbnail 
    thumbnail_replace = kwargs.get('thumbnail_replace', False) # does thumbnail image replace crop image? 

    screen_path = abspath(path, filename) 
    crop_path = thumbnail_path = screen_path 

    if thumbnail and not crop: 
     raise Exception, 'Thumnail generation requires crop image, set crop=True' 

    do_screen_capturing(url, screen_path, width, height) 

    if crop: 
     if not crop_replace: 
      crop_path = abspath(path, 'crop_'+filename) 
     params = { 
      'width': crop_width, 'height': crop_height, 
      'crop_path': crop_path, 'screen_path': screen_path} 
     do_crop(params) 

     if thumbnail: 
      if not thumbnail_replace: 
       thumbnail_path = abspath(path, 'thumbnail_'+filename) 
      params = { 
       'width': thumbnail_width, 'height': thumbnail_height, 
       'thumbnail_path': thumbnail_path, 'crop_path': crop_path} 
      do_thumbnail(params) 
    return screen_path, crop_path, thumbnail_path 


if __name__ == '__main__': 
    ''' 
     Requirements: 
     Install NodeJS 
     Using Node's package manager install phantomjs: npm -g install phantomjs 
     install selenium (in your virtualenv, if you are using that) 
     install imageMagick 
     add phantomjs to system path (on windows) 
    ''' 

    url = 'http://stackoverflow.com/questions/1197172/how-can-i-take-a-screenshot-image-of-a-website-using-python' 
    screen_path, crop_path, thumbnail_path = get_screen_shot(
     url=url, filename='sof.png', 
     crop=True, crop_replace=False, 
     thumbnail=True, thumbnail_replace=False, 
     thumbnail_width=200, thumbnail_height=150, 
    ) 

Estas son las imágenes generadas:

+0

Funciona perfectamente en mi vista de Django. No es necesario configurar el agente de usuario predeterminado, solo la resolución de pantalla. – serfer2

+0

¿Qué pasa si una página web requiere certificados de acceso? –

+2

La pregunta era para Python, no NodeJS. –

-1

probar este ..

#!/usr/bin/env python 

import gtk.gdk 

import time 

import random 

while 1 : 
    # generate a random time between 120 and 300 sec 
    random_time = random.randrange(120,300) 

    # 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.time() 
    filename = "screenshot" 
    filename += str(ts) 
    filename += ".png" 

    if (pb != None): 
     pb.save(filename,"png") 
     print "Screenshot saved to "+filename 
    else: 
     print "Unable to get the screenshot." 
Cuestiones relacionadas