web-dev-qa-db-fra.com

Comment puis-je prendre une capture d'écran / image d'un site Web en utilisant Python?

Ce que je veux réaliser, c'est obtenir une capture d'écran d'un site Web à partir de n'importe quel site Web en python.

Env: Linux

49
Esteban Feldman

Sur le Mac, il y a webkit2png et sur Linux + KDE, vous pouvez utiliser khtml2png . J'ai essayé le premier et cela fonctionne assez bien, et j'ai entendu parler de ce dernier étant utilisé.

J'ai récemment rencontré QtWebKit qui prétend être multiplateforme (Qt a roulé WebKit dans leur bibliothèque, je suppose). Mais je ne l'ai jamais essayé, donc je ne peux pas vous en dire plus.

Les liens QtWebKit montrent comment accéder à partir de Python. Vous devriez pouvoir utiliser au moins un sous-processus pour faire de même avec les autres.

11
ars

Voici une solution simple utilisant 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')
44
hoju

Voici ma solution en récupérant l'aide de diverses sources. Il prend la capture d'écran de la page Web complète et la recadre (facultatif) et génère également une miniature à partir de l'image recadrée. Voici les exigences:

Exigences:

  1. Installer NodeJS
  2. En utilisant le gestionnaire de paquets de Node, installez phantomjs: npm -g install phantomjs
  3. Installez Selenium (dans votre virtualenv, si vous l'utilisez)
  4. Installer imageMagick
  5. Ajouter des fantômes au chemin système (sous 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 __== '__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,
    )

Ce sont les images générées:

35
Aamir Adnan

Je ne peux pas commenter la réponse d'ars, mais j'ai en fait le code de Roland Tapken fonctionnant en utilisant QtWebkit et cela fonctionne assez bien.

Je voulais juste confirmer que ce que Roland publie sur son blog fonctionne très bien sur Ubuntu. Notre version de production n'a finalement utilisé aucun de ses écrits, mais nous utilisons les liaisons PyQt/QtWebKit avec beaucoup de succès.

5
aezell

peut faire en utilisant du sélénium

from Selenium import webdriver

DRIVER = 'chromedriver'
driver = webdriver.Chrome(DRIVER)
driver.get('https://www.spotify.com')
screenshot = driver.save_screenshot('my_screenshot.png')
driver.quit()

https://sites.google.com/a/chromium.org/chromedriver/getting-started

5
Joolah

Utiliser Rendertron est une option. Sous le capot, il s'agit d'un Chrome exposant les points de terminaison suivants:

  • /render/:url : accédez à cet itinéraire, par exemple avec requests.get si vous êtes intéressé par le DOM.
  • /screenshot/:url : accédez à cet itinéraire si vous êtes intéressé par une capture d'écran.

Vous installez rendertron avec npm, exécutez rendertron dans un terminal, accédez à http://localhost:3000/screenshot/:url et enregistrez le fichier, mais une démo est disponible sur render-tron.appspot.com permettant d'exécuter localement cet extrait Python3 sans installer le paquet npm:

import requests

BASE = 'https://render-tron.appspot.com/screenshot/'
url = 'https://google.com'
path = 'target.jpg'
response = requests.get(BASE + url, stream=True)
# save file, see https://stackoverflow.com/a/13137873/7665691
if response.status_code == 200:
    with open(path, 'wb') as file:
        for chunk in response:
            file.write(chunk)
1
Michael H.

Vous ne mentionnez pas l'environnement dans lequel vous exécutez, ce qui fait une grande différence car il n'y a pas de navigateur Web pur Python capable de rendre HTML.

Mais si vous utilisez un Mac, j'ai utilisé webkit2png avec beaucoup de succès. Sinon, comme d'autres l'ont souligné, il existe de nombreuses options.

0
Daniel Naab