[Python3] Prenez une capture d'écran d'une page Web sur le serveur et recadrez-la davantage

introduction

** Ce que je voulais faire ** Je veux prendre une capture d'écran d'une page Web sur heroku et la recadrer avec un élément HTML.

problème Lors de l'exécution de PhantomJS avec du sélénium, il n'existe aucune méthode pour obtenir l'emplacement de la position de l'élément.

Solution Exécutez Javascript avec la fonction ʻexecute_script fournie dans la classe selenium.webdriver.PhantomJS`.

environnement

** Bibliothèque Python **

Code minimal

screenshot_crop.py


from PIL import Image
from selenium import webdriver

driver = webdriver.PhantomJS()
driver.get("https://www.yahoo.co.jp")  # (1)
driver.save_screenshot("screenshot.png ")  # (2)


element_type = "Id"  # (3)
element_name = "topicsboxbd"  # (4)

before_script = """
                var element = document.getElementBy""" + element_type + "('" + element_name + """');
                var rect = element.getBoundingClientRect(); 
                """  # (5)
left = driver.execute_script(before_script + "return rect.left;")  # (6)
top = driver.execute_script(before_script + "return rect.top;")  # (6)

right = driver.execute_script(before_script + "return rect.width;") + left  # (7)
bottom = driver.execute_script(before_script + "return rect.height;") + top  # (7)

im = Image.open("screenshot.png ")  # (8) 
im = im.crop((left, top, right, bottom))  # (9)
im.save("screenshot_crop.png ")  # (10)
im.close()

Commentaire

(1) - Spécifiez l'URL pour prendre la capture d'écran. (2) -Enregistrer une capture d'écran de la page entière. (3) --Spécifiez le nom de l'attribut d'élément (Id, Classe, etc.) dans ʻelement_type. Tout peut être saisi dans le cercle Javascript getElementBy 〇〇. Par conséquent, la chaîne de caractères à attribuer doit commencer par une lettre supérieure. (4) --Spécifiez la valeur d'attribut (partie principale telle que id = "main") de l'attribut spécifié dans (3) de l'élément dans ʻelement_name. (5) - Partie commune du code JS à exécuter (6) (7) --Le code Javascript est exécuté par la fonction driver.execute_script pour obtenir les coordonnées en haut à gauche et en bas à droite de l'élément. (8) -Ouvrez la capture d'écran enregistrée dans (1). (9) -Cadrer la capture d'écran originale en utilisant les coordonnées obtenues en (6) et (7). (10) --Enregistrez la capture d'écran recadrée.

Résultat d'exécution

screenshot.png Capture d'écran de la page entière screenshot.png

screenshot_crop.png Capture d'écran de screenshot.png recadrée avec l'élément ʻid = "topicsboxbd" ʻelement screenshot_crop.png

Lors de l'exécution sur heroku

Lorsque je mets PhantomJS sur heroku et que je prends une capture d'écran, le japonais n'est pas affiché tel quel dans l'image enregistrée. En créant un répertoire .font dans le répertoire racine et en insérant un fichier ttf (otf) prenant en charge le japonais, le japonais sera affiché.

Utilisation de phantomjs avec Heroku | Program Memo

J'ai créé mon propre module

exphantom.py


from PIL import Image
from selenium import webdriver


class ScreenShot:
    def __init__(self, file_name_: str = "screenshot.png "):
        """
        :type file_name_: str
        """
        self._filename = file_name_
        self._driver = webdriver.PhantomJS()
        self._driver.set_window_size(1024, 768)
        self._crop_margin = 0

    def screen_shot(self, url_: str) -> bool:
        """
        Take a screenshot of the specified url.
        :return: Success is True, Fail is False
        :param url_: the webpage to save screenshot
        """
        try:
            self._driver.get(url_)
            self._driver.save_screenshot(self._filename)
        except Exception as e:
            print(e)
            return False
        return True

    def screen_shot_crop(self, url_: str, search_element_name: str, search_element_type: str = "Id") -> bool:
        """
        Take a screenshot of the specified class of the specified url destination.
        :return: Success is True, Fail is False
        :param url_: the webpage to save screenshot
        :param search_element_name: search to element name
        :param search_element_type: search to element type
        """
        self.screen_shot(url_)
        before_script = """
                        var element = document.getElementBy""" + search_element_type + "('" + search_element_name + """');
                        var rect = element.getBoundingClientRect(); 
                        """
        try:
            left = self._driver.execute_script(before_script + "return rect.left;") - self._crop_margin
            top = self._driver.execute_script(before_script + "return rect.top;")
            right = self._driver.execute_script(before_script + "return rect.width;") + left + self._crop_margin
            bottom = self._driver.execute_script(before_script + "return rect.height;") + top + self._crop_margin
        except Exception as e:
            print(e)
            return False
        im = Image.open(self._filename)
        im = im.crop((left, top, right, bottom))
        im.save(self._filename)
        im.close()
        return True

    def set_file_name(self, filename_: str):
        self._filename = filename_

    def set_window_size(self, width_: int, height_: int):
        self._driver.set_window_size(width=width_, height=height_)

    def get_window_size(self) -> object:
        return self._driver.get_window_size()

    def set_crop_margin(self, crop_margin_: int):
        self._crop_margin = crop_margin_

    def ger_crop_margin(self) -> object:
        return self._crop_margin

    def __del__(self):
        self._driver.close()


if __name__ == "__main__":
    #Spécifiez l'URL pour prendre une capture d'écran
    screen_url = "https://www.yahoo.co.jp"
    #Spécifiez les attributs de l'élément à recadrer
    element_type = "Id"
    #Spécifiez le nom de l'élément à recadrer
    element_name = "topicsboxbd"
    #Spécifiez le nom du fichier de destination d'enregistrement lors de la création d'une instance
    ss = ScreenShot("screenshot.png ")
    # screen_Enregistrer la capture d'écran de l'URL
    ss.screen_shot(screen_url)
    #Changer le nom du fichier de destination d'enregistrement
    ss.set_file_name("screenshot_crop.png ")
    # screen_élément url_élément de type attribut_Enregistrer une capture d'écran de l'élément nommé name
    ss.screen_shot_crop(screen_url, element_name, element_type)
    #Supprimer l'instance
    del ss

Situé sur GitHub

** Exemple d'utilisation réelle ** [Non officiel] Miyadai Support Division Notice BOT

référence

python selenium phantomJS element.location returns wrong location - Stack Overflow

Recommended Posts

[Python3] Prenez une capture d'écran d'une page Web sur le serveur et recadrez-la davantage
Obtenez la page Web Python, encodez et affichez les caractères
[python, ruby] sélénium-Obtenez le contenu d'une page Web avec le pilote Web
Python VBA pour obtenir une capture de la page WEB entière avec Selenium
[Mémo personnel] Obtenez des données sur le Web et faites-en un DataFrame
Lancer un serveur Web avec Python et Flask
Prise en compte des forces et faiblesses de Python
Prenez des captures d'écran LCD avec Python-LEGO Mindstorms
Exécuter une commande sur le serveur Web et afficher le résultat
Installez django sur python + anaconda et démarrez le serveur
Le résultat de la création d'un album de cartes de jeunes mariés italiens en Python et de son partage
Je souhaite prendre une capture d'écran du site sur Docker en utilisant n'importe quelle police
Prendre une capture d'écran en Python
Récupérer une image d'une page Web et la redimensionner
Test.py n'est pas reflété sur le serveur Web dans Python3.
Créer un environnement Python et transférer des données vers le serveur
[Introduction à AWS] Mémorandum de création d'un serveur Web sur AWS
Le processus de création et d'amélioration du code Python orienté objet
Récupérez la chaîne correspondante dans l'expression régulière et réutilisez-la lors du remplacement sur Python3
Comment démarrer un serveur WEB simple qui peut exécuter des cgi de php et python
J'ai créé une fonction pour découper l'image de python openCV, alors veuillez l'utiliser.
[Python] Enregistrez le résultat du scraping Web de la page produit Mercari sur Google Colab dans une feuille de calcul Google et affichez également l'image du produit.
L'histoire de Python et l'histoire de NaN
Automatisation d'une recherche sur des informations géographiques telles que le réseau de magasins à l'aide de Python et de l'API Web
Installez mecab sur le serveur partagé Sakura et appelez-le depuis python
[PEP8] Reprenez le code source Python et écrivez-le proprement
Spécifiez ou créez un dossier python, puis enregistrez la capture d'écran.
Observation en virgule fixe de données spécifiques sur le Web en exécutant automatiquement un navigateur Web sur le serveur (Ubuntu16.04) (2) -Web scraping-
[Python] Le rôle de l'astérisque devant la variable. Divisez la valeur d'entrée et affectez-la à une variable
Convertissez le résultat de python optparse en dict et utilisez-le
Obtenez le nombre de lecteurs d'articles sur Mendeley en Python
[Python / Jupyter] Traduisez le commentaire du programme copié dans le presse-papiers et insérez-le dans une nouvelle cellule.
Configurer un serveur SMTP factice avec Python et vérifier le fonctionnement de l'envoi depuis Action Mailer
[Python] J'ai analysé le journal d'un homme au cours de sa première année de vie professionnelle et j'ai fait un jugement positif / négatif sur la vie professionnelle.
J'ai essayé de pousser les documents Sphinx vers BitBucket et de les refléter automatiquement sur le serveur Web
Utilisez AWS lambda pour récupérer les actualités et notifier régulièrement LINE des mises à jour [python]
Introduction et utilisation de la bouteille Python ・ Essayez de configurer un serveur Web simple avec une fonction de connexion
Jetons un coup d'œil au code Scapy. Surcharge des méthodes spéciales __div__, __getitem__.
Mettez à jour les données en les téléchargeant sur s3 d'aws avec une commande, et supprimez les données utilisées (en chemin)
Obtenez la largeur du div côté serveur avec Selenium + PhantomJS + Python
Calculer l'itinéraire le plus court d'un graphe avec la méthode Dyxtra et Python
Hit une méthode d'une instance de classe avec l'API Web Python Bottle
Déployer et utiliser le modèle de prédiction créé en Python sur SQL Server
Démarrez la webcam, prenez une image fixe et enregistrez-la localement
[python] Envoyez l'image capturée de la caméra Web au serveur et enregistrez-la
Résumez le titre de Hottentori dans Hateb et regardez le présent du Web
Installez Python3 et Django sur Amazon Linux (EC2) et exécutez le serveur Web
Un mémo contenant Python2.7 et Python3 dans CentOS
Connectez beaucoup de Python ou et et
Télécharger des fichiers sur le Web avec Python
[python] [meta] Le type de python est-il un type?
Configurons un serveur WEB avec Chromebook
L'histoire du traitement A du blackjack (python)
[Python] Une barre de progression sur le terminal
Publier le répertoire actuel sur le serveur Web
[Python] N'est-ce pas le plus élevé et le plus élevé si vous pouvez saisir les caractéristiques d'une entreprise avec nlplot?
[Python] J'ai créé un code de scraping web qui acquiert automatiquement le titre de l'actualité et l'URL de Nihon Keizai Shimbun.