Auslesen JSON Datenbank

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Andorso
User
Beiträge: 5
Registriert: Freitag 12. April 2024, 11:45

Hallo Zusammen,

ich habe ein kleines Problem wo ich einfach keine Lösung finde.
Ich versuche aus einer data.json meine Daten auszulesen. Jedoch bekomme ich einen KeyError. ich habe zuerst gedacht es gibt hier Rechtschreibfehler, aber ich sorgfältiger Überprüfung habe ich das auch ausgeschlossen. So schaut mein Code aus:

import json

with open('data.json') as f:
config = json.load(f)

images = config['images']['url_screenshot']

for key, url in images.items():
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--start-maximized")
driver = webdriver.Chrome(options=chrome_options)
driver.get(url)

sleep(4)

image_folder = os.path.expanduser(images["folders"][key])
screenshot1_path = make_screenshot(image_folder)

sleep(1)

driver.quit()

sleep(2)

if click_image(images["chrome"][0]):
time.sleep(1)
click_image(images["double_arrows"][0])
time.sleep(1)
try:
find_image(images["website"][key][0])
time.sleep(1)
click_image(images["website"][key][0])
except pyautogui.ImageNotFoundException:
try:
doubleclick_image(images["fullscreen"][0])
time.sleep(1)
click_image(images["website"][key][0])
time.sleep(1)
except pyautogui.ImageNotFoundException:
try:
click_image(images["website"][key][0])
except pyautogui.ImageNotFoundException:
time.sleep(1)
click_image(images["website"][key][0 +1])


Ich habe hier nur einen Abschnitt meines Codes ohne die Funktionen eingefügt. Meine eigentliche Frage hier ist, kann man hier auf die Variablen vom Json zugreifen wie in Javascript, mit denen man durch eine Schleife durch das json durch geht bei jedem neuen Durchgang? Was mache ich hier flalsch :(

hier meine passende Datenbank.

"images": {
"chrome": "scriptimages/chrome.png",
"double_arrow": "scriptimages/double-arrow.png",
"url_screenshot": {
"a1": "https://www.a1.de/",
"a2": "https://www.a2.de/",
"a3": "https://www.a3.de/",
"a4": "https://www.a4.de/",
"a5": "https://www.a5.de/",
"a6": "https://www.a6.de/",
"a7": "https://www.a7.de/",
"a8": "https://www.a8.de/",
"a9": "https://www.a9.de/",
"a10": "https://www.a10.de/",
"a11": "https://www.a11.de/",
"a12": "https://www.a12.de/",
"a13": "https://www.a13.de/",
"a14": "https://www.a14.de/"
}
} ab hier geht mein json noch weiter aber für die frage sollte der Abschnitt reichen :). die a1 - a14 sind nur schematische Einträge.

Vielen Dank im Voraus.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Du solltest deinen Code hier ordentlich formatiert einstellen, ansonsten ist er aufgrund der fehlenden Einrückungen nicht verständlich. Zudem solltest du bei einem Fehler die exakte und volle Fehlermeldung (Traceback) bereitstellen.

Was ich aber auf Anhieb sehe: Du versuchst auf images["double_arrows"] zuzugreifen, aber "double_arrows" ist kein vorhandener Key.
Sirius3
User
Beiträge: 17761
Registriert: Sonntag 21. Oktober 2012, 17:20

Bitte Code in code-Tags posten, so dass die Einrückung nicht verloren geht. Bitte den vollständigen Traceback posten. An welcher Stelle tritt der Fehler auf? Wie ist die exakte Fehlermeldung?
Was man sofort sieht, ist, dass es wahrscheinlich kein `images["folders"]` gibt.
Ebensowenig ein `images["chrome"][0]` wo zusätzlich die [0] komisch aussieht.
Benutzeravatar
grubenfox
User
Beiträge: 433
Registriert: Freitag 2. Dezember 2022, 15:49

nicht zu vergessen `images ["fullscreen"]` und `images["website"]` ...
Andorso
User
Beiträge: 5
Registriert: Freitag 12. April 2024, 11:45

wie kann ich das als code Editor richtig posten mit den richtigen Einrückungen. ich habe das in anderen Beiträgen gesehen aber irgendwie finde ich das nicht. ich kann euch dann den gesamten code posten. und wie ich vorgehe.

kurz gesagt. ab der for-schleife möchte ich auf den json zugreifen und dann auf die einzelnen zweige in dem jeweiligen abschnitt. den Parameter [0] benutze ich damit er aus dem json nur wirklich auf den ersten wert zugreift, weil hier noch weitere von mir später eingetragen werden, jedoch erst mal unberührt bleiben sollen. die werte die mit einem "key" versehen sind, sollen mit der schleife bei jedem vollem Durchgang durchgegangen werden.
Benutzeravatar
noisefloor
User
Beiträge: 3858
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

du hast da scheinbar noch ein Verständnisproblem beim Zugriff. Der Index-Zugriff mit z.B. [0] funktioniert, wenn der Datenstruktur ein Array ist (was in Python auf eine Liste abgebildet wird) - hast du aber im Beispiel nicht. Du hast nur Objekte im gezeigten JSON (was in Python auf ein Dict abgebildet wird), d.h. der Zugriff erfolgt dann über den Schlüssel, nicht den Index.

Gruß, noisefloor
Andorso
User
Beiträge: 5
Registriert: Freitag 12. April 2024, 11:45

Hallo Noisefloor,

vielen dank für die Info. Ja es stimmt ich habe ein JSON und kein Array. Wie kann ich mit python dynamisch darauf zugreifen, dass mit jedem Start der Schleife ein neuer Wert auf den Key übergeben wird. Hierbei habe ich auch schon ziemlich überall geschaut ob ich da eine Lösung finde und ich bin schon seit Tagen an dem Problem dran :( . Ich dachte mir "spätestens jetzt melde ich mich in der Comunity an" :)

Gruß zurück :)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Code wird durch code-Tags vernuenftig formatiert, das ist der </>-Knopf im vollstaendigen Editor, oder einfach
[code*]
mein code
[/code*]
ohne die * benutzen.

Was deine Frage angeht: du hast ein Woerterbuch, und darauf greift man zB so zu:

Code: Alles auswählen

for schluessel, wert in woerterbuch.items():
   ...
Sirius3
User
Beiträge: 17761
Registriert: Sonntag 21. Oktober 2012, 17:20

Der erste Schritt ist, sich mit Python und dem Zugriff auf Wörterbücher und Listen vertraut zu machen. Heißt, lade das Json in einer interaktiven Pythonsitzung und hangel Dich durch die Datenstruktur durch, bis Du in der Verwendung sicher bist, dann schreibst Du einfache Schleifen und gib dir die Variablen per print aus, um zu prüfen, ob das, was Du denkst auch das ist, was das Programm sagt.
Andorso
User
Beiträge: 5
Registriert: Freitag 12. April 2024, 11:45

Code: Alles auswählen

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import datetime
import os
import sys
import cv2
import numpy as np
import pyautogui
sys.path.append("c:\\python311\\lib\\site-packages")
from pyautogui import locateCenterOnScreen, click
import time
from time import sleep
from skimage.metrics import structural_similarity as ssim
from PIL import Image
import json

green_star = False

def click_image(image):
    script_dir = os.path.dirname(os.path.realpath(__file__))
    image_path = os.path.join(script_dir, image)
    position = locateCenterOnScreen(image_path, confidence=0.9)
    if position:
        x, y = position
        click(x, y, clicks=1, interval=0.25)
        return True
    else:
        print(f"{image} wurde nicht gefunden.")
        return False

def doubleclick_image(image):
    script_dir = os.path.dirname(os.path.realpath(__file__))
    image_path = os.path.join(script_dir, image)
    position = locateCenterOnScreen(image, confidence=0.9)
    if position:
        x, y = position
        click(x, y, clicks=2, interval=0.25)
        return True

def make_screenshot(image_folder):     
    screenshot = pyautogui.screenshot()
    filename = f"Screenshot_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
    screenshot_path = os.path.join(image_folder, filename)
    screenshot.save(screenshot_path)
    print(f"Screenshot gespeichert: {screenshot_path}")
    return screenshot_path


# funktion geändert
def find_image(image):
    script_dir = os.path.dirname(os.path.realpath(__file__))
    image_path = os.path.join(script_dir, image)
    global green_star
    position = pyautogui.locateCenterOnScreen(image_path, confidence=0.9)
    if position:
        green_star = True
    else:
        green_star = False

def compare_images(image1_path, image2_path, output_folder):
    if not os.path.isfile(image1_path):
        print(f"Fehler: Das Bild {image1_path} existiert nicht.")
        return None, None
    if not os.path.isfile(image2_path):
        print(f"Fehler: Das Bild {image2_path} existiert nicht.")
        return None, None

    image1 = cv2.imread(image1_path)
    image2 = cv2.imread(image2_path)

    gray_image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
    gray_image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

    score, diff = ssim(gray_image1, gray_image2, full=True)
    diff = (diff * 255).astype("uint8")  

    thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
    contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    for c in contours:
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(image1, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.rectangle(image2, (x, y), (x + w, y + h), (0, 0, 255), 2)

    result = np.concatenate((image1, image2), axis=1)

    result_filename = f"Vergleich_vom_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
    result_path = os.path.join(output_folder, result_filename)
    cv2.imwrite(result_path, result)
    print(f"Vergleich gespeichert: {result_path}")

    return score, result_path

with open("data.json", "r") as f:
    config = json.load(f)

images = config['images']['url_screenshot']
image_ordner = config['images']['folders']

for key, url in images.items():
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument("--start-maximized")
    driver = webdriver.Chrome(options=chrome_options)  
    driver.get(url)

    sleep(4) 
        
    image_folder = os.path.expanduser(image_ordner[key])
    screenshot1_path = make_screenshot(image_folder)
   
    sleep(1)

    driver.quit()

    sleep(2)

    if click_image(images["chrome"][0]):
        print('Öffne Chromebrowser')  

        time.sleep(1)

        click_image(images["double_arrows"][0])
        print('Benutze Doppelpfeile oben rechts')

        time.sleep(1)
    
        try:
            find_image(images["website"][key][0])
            print("erste Bildgefunden")
            time.sleep(1)
            click_image(images["website"][key][0])
            print('Öffne die Webseite')
        except pyautogui.ImageNotFoundException:
            try:
                print("erste Bild nicht gefunden, da kein Fullscreen")
                doubleclick_image(images["fullscreen"][0])
                time.sleep(1)
                click_image(images["website"][key][0])
                print('Öffne die Webseite')
                time.sleep(1)
            except pyautogui.ImageNotFoundException:
                try:
                    click_image(images["website"][key][0])
                    print('Öffne die Webseite')  
                except pyautogui.ImageNotFoundException:
                    time.sleep(1)
                    click_image(images["website"][key][0 +1])

        time.sleep(1)
    
        try:
            click_image(images["bitwarden"][0])
            print('Öffne Bitwarden')   
        except pyautogui.ImageNotFoundException:
            click_image(images["bitwarden"][1])
            print('Öffne Bitwarden')

        time.sleep(1)
    
        click_image(images["zugangsdaten"][key][0])
        print('Benutze Zugangsdaten')

        time.sleep(2)
    
        click_image(images["login"][0])
        print('Klicke auf Login... bitte Yubikey verwenden')

        time.sleep(10)
        
        click_image(images["components"][0])
        print('Öffne Komponenten')

        time.sleep(1)
    
        click_image(images["akeeba"][0])
        print('Öffne Akeeba Backup')
    
        time.sleep(1)

        click_image(images["control_panel"][0])
        print('Öffne Controlpanel')

        time.sleep(1)
    
        click_image(images["start"][0])
        print('Beginne mit dem Backup')

        time.sleep(5)

        while True:
            try:
                find_image(images["back_control_panel"][0])
                break 
            except pyautogui.ImageNotFoundException:
                print("Update noch im Gange...")
                time.sleep(5)

        time.sleep(3)

        click_image(images["back_control_panel"][0])
    
        time.sleep(3)
    
        click_image(images["yoomla_home"][0])

        time.sleep(3)
    
        try:
            find_image(images["green_star"][0])
        except pyautogui.ImageNotFoundException:
            print("Sieht aus als müssten Updates gemacht werden.")
            green_star = False

        time.sleep(3)

        if  green_star:
            print("updates sind akutell")
            click_image(images["green_star"][0])
            time.sleep(5)
            click_image(images["yoomla_home"][0])
        else: 
            print("müssen aktualisiert werden")
            click_image(images["red_star"][0])
            time.sleep(3)
            while True:
                try: 
                    click_image(images["checkbox"][0])
                    time.sleep(3)
                    click_image(images["update_btn"][0])
                    time.sleep(15)
                    click_image(images["yoomla_home"][0])
                    break             
                except pyautogui.ImageNotFoundException:
                    print("warte auf weiterleitung....")
                    time.sleep(5)
    
        time.sleep(3)
    
        click_image(images["close_window"][0]) 

        time.sleep(3)   
    
        chrome_options = webdriver.ChromeOptions()
        chrome_options.add_argument("--start-maximized")
        driver = webdriver.Chrome(options=chrome_options)  
        driver.get(url)
        sleep(4) 

        image_folder = os.path.expanduser(folders[key])
        screenshot2_path = make_screenshot(image_folder)  

        sleep(1) 
        driver.quit()

        output_folder = os.path.expanduser(folders[key])

        sleep(5)

        if screenshot1_path and screenshot2_path:
            similarity_score, result_path = compare_images(screenshot1_path, screenshot2_path, image_folder)

            if similarity_score is not None and result_path is not None:
                print(f"Ähnlichkeitsindex (SSIM): {similarity_score}")
                print(f"Vergleich gespeichert: {result_path}")
und hier wäre mein JSON komplett.

Code: Alles auswählen


{
    "images": {
      "chrome": "scriptimages/chrome.png",
      "double_arrow": "scriptimages/double-arrow.png",
      "url_screenshot": {      
        "aust_it": "https://www.aust-it.de/",
        "aerzte_ffb": "https://www.aerzte-ffb.de/",
        "aekv_weilheim_schonberg": "https://www.aekv-weilheim-schongau.de/",
        "aekv_traunstein": "https://www.aekv-traunstein.de/",
        "aekv_rosenheim": "https://www.aekv-rosenheim.de/",
        "aekv_pfaffenhofen": "https://www.aekv-pfaffenhofen.de/",
        "aekv_mittelschwaben": "https://www.aekv-mittelschwaben.de/",
        "aekv_miesbach": "https://www.aekv-miesbach.de/",
        "aekv_garmisch_partenkirchen": "https://aekv-garmisch-partenkirchen.de/",
        "aekv_ebersberg": "https://www.aekv-ebersberg.de/",
        "aekv_dachau": "https://www.aekv-dachau.de/",
        "aekv_badtoelzwolfratshausen": "https://www.aekv-badtoelzwolfratshausen.de/",
        "aebv_schwaben": "https://www.aebv-schwaben.de/",
        "aebo": "https://www.aebo.de/"
      },      
      "webseite": {
        "aust_it": ["scriptimages/aust-it.png", "scriptimages/aust-it2.png"],
        "aerzte_ffb": "scriptimages/aerzte-ffb.png",
        "aekv_weilheim_schonberg": "scriptimages/aekv-weilheim-schonberg.png",
        "aekv_traunstein": "scriptimages/aekv-traunstein.png",
        "aekv_rosenheim": "scriptimages/aekv-rosenheim.png",
        "aekv_pfaffenhofen": "scriptimages/aekv-pfaffenhofen.png",
        "aekv_mittelschwaben": "scriptimages/aekv-mittelschwaben.png",
        "aekv_miesbach": "scriptimages/aekv-miesbach.png",
        "aekv_garmisch_partenkirchen": "scriptimages/aekv-garmischpartenkirchen.png",
        "aekv_ebersberg": "scriptimages/aekv-ebersberg.png",
        "aekv_dachau": "scriptimages/aekv-dachau.png",
        "aekv_badtoelzwolfratshausen": "scriptimages/aekv-badtoelzwolfratshausen.png",
        "aebv_schwaben": "scriptimages/aebv-schwaben.png",
        "aebo": "scriptimages/aebo.png"
      },
      "bitwarden": {
        "bw": "scriptimages/bw.png",
        "bw1": "scriptimages/bw1.png"
      },
      "folders": {
        "screenshot_aust_it": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aust-it",
        "screenshot_aerzte_ffb": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aerzte-ffb",
        "screenshot_aekv_weilheim_schonberg": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-weilheim-schonberg",
        "screenshot_aekv_traunstein": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-traunstein",
        "screenshot_aekv_rosenheim": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-rosenheim",
        "screenshot_aekv_pfaffenhofen": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-pfaffenhofen",
        "screenshot_aekv_mittelschwaben": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-mittelschwaben",
        "screenshot_aekv_miesbach": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-miesbach",
        "screenshot_aekv_garmisch_partenkirchen": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-garmisch-partenkirchen",
        "screenshot_aekv_ebersberg": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-ebersberg",
        "screenshot_aekv_dachau": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-dachau",
        "screenshot_aekv_badtoelzwolfratshausen": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aekv-badtoelzwolfratshausen",
        "screenshot_aebv_schwaben": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aebv-schwaben",
        "screenshot_aebo": "~\\aust it services\\Kommunikationswebsite - Dokumente\\Mitarbeiter_Daten\\Shared\\webseiten_automatisierung\\screenshots\\aebo"
      },
      "zugangsdaten": {
        "aust_it_bw": "scriptimages/aust-it-bw.png",
        "aerzte_ffb_bw": "scriptimages/aerzte-ffb-bw.png",
        "aekv_weilheim_schonberg_bw": "scriptimages/aekv-weilheim-schonberg-bw.png",
        "aekv_traunstein_bw": "scriptimages/aekv-traunstein-bw.png",
        "aekv_rosenheim": "scriptimages/aekv-rosenheim-bw.png",
        "aekv_pfaffenhofen": "scriptimages/aekv-pfaffenhofen-bw.png",
        "aekv_mittelschwaben": "aekv-mittelschwaben-bw.png",
        "aekv_miesbach": "scriptimages/aekv-miesbach-bw.png",
        "aekv_garmisch_partenkirchen": "scriptimages/aekv-garmisch-partenkirchen-bw.png",
        "aekv_ebersberg": "scriptimages/aekv-ebersberg-bw.png",
        "aekv_dachau": "scriptimages/aekv-dachau-bw.png",
        "aekv_badtoelzwolfratshausen": "scriptimages/aekv-badtoelzwolfratshausen-bw.png",
        "aebv_schwaben": "scriptimages/aebv-schwaben-bw.png",
        "aebo": "scriptimages/aebo-bw.png"
      },
      "login": "scriptimages/login.png",
      "components": "scriptimages/components.png",
      "akeeba": "scriptimages/akeeba.png",
      "control_panel": "scriptimages/control-panel.png",
      "start": "scriptimages/start.png",
      "back_control_panel": "scriptimages/back-control-panel.png",
      "yoomla_home": "scriptimages/yoomla-home.png",
      "green_star": "scriptimages/green-star.png",
      "red_star": "scriptimages/red-star.png",
      "checkbox": "scriptimages/checkbox.png",
      "update_btn": "scriptimages/update-btn.png",
      "close_window": "scriptimages/close-window.png",
      "fullscreen": "scriptimages/fullscreen.png"
    }   
  }

ich glaube das ist so einfach zu erkennen was ich machen möchte. Hierbei bekome ihc den keyError weil die keys so nicht gefunden werden. :(
Benutzeravatar
noisefloor
User
Beiträge: 3858
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

die Antwort bleibt die gleiche... Und es gibt sowieso keine Key "double_arrows", nur "double_arrow".

Ansonsten solltest du den Tipp von @Sirius3 beherzigen und umsetzen.

Gruß, noisefloor
Andorso
User
Beiträge: 5
Registriert: Freitag 12. April 2024, 11:45

alles klar ich versuche es vielen Dank :D
Benutzeravatar
__blackjack__
User
Beiträge: 13123
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Andorso: Die ``[0]`` sind alle falsch weil in dem gesamten JSON kein einziges Array vorkommt.

Die Aufteilung der Daten ist IMHO auch falsch. Du hast da verschiedene parallele Wörterbücher wo Werte mit dem gleichen Schlüssel eigentlich zusammengehören. Das ist fehleranfällig beim schreiben/verändern der Daten und auch unübersichtlich, weil zusammengehörende Daten nicht zusammen sondern verteilt gespeichert werden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13123
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Andorso: Anmerkungen zum Quelltext:

Die Importe sollte man mal aufräumen. Also mindestens mal etwas sortieren und unbenutzes entfernen.

`time` wird importiert um daraus `sleep()` aufzurufen, aber `sleep()` wird auch noch mal explizit importiert. Wonach wurde denn entschieden wann welcher Weg gewählt wird? Das sollte vereinheitlicht werden. Ebenso `pyautogui` und was daraus importiert wird.

Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. Der Name soll dem Leser vermitteln was der Wert dahinter im Programm bedeutet, nicht zum rätseln zwingen. `structural_similarity()` beim Import als `ssim()` abzukürzen bringt nicht wirklich etwas.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

``global`` hat in einem sauberen Programm nichts zu suchen. Das ist hier ja auch nur ein übler Hack wo man eigentlich einen Rückgabewert verwenden würde. So richtig übel ist auch das viele `find_image()`-Aufrufe diese globale Variable verändern, aber nur ein einziger davon etwas mit einem grünen Stern zu tun hat. Bei allen anderen wird der Wert einfach ignoriert. *Dafür* eine globale Variable zu verwenden die von völlig unbeteiligten Aufrufen verändert wird ist extrem unübersichtlich und auch fehleranfällig. Zudem wird der Initialwert der ganz am Anfang gesetzt wird, nie irgendwo verwendet.

Statt `os.path` & Co verwendet man in neuem Code `pathlib`.

Das Verzeichnis des Programms sollte man einmal am Anfang als Konstante ermitteln.

`click_image()` und `doubleclick_image()` sind fast identisch. Die sollten eigentlich noch ähnlicher sein, denn die unterscheiden sich ja einzig durch die Anzahl der Mausklicks.

Die Tests auf den Rückgabewert von `locateCenterOnScreen()` machen keinen Sinn, denn die Funktion gibt entweder ein Tupel zurück oder löst eine Ausnahme aus. Damit macht dann aber auch der Rückgabewert keinen Sinn denn der ist *immer* `True` weil im anderen Fall ja eine Ausnahme ausgelöst wird. Das gilt auch für `find_image()`.

Das starten eines Browsers mittels `webdriver` passiert zweimal mit identischem Code und beide male vor einem Bildschirmfoto. Das sollte mindestens in eine eigene Funktion herausgezogen werden, oder in die `make_screenshot()` wandern.

``if screenshot1_path and screenshot2_path:`` ist immer wahr, kann also raus.

Und auch `similarity_score` und `result_path` braucht man nicht prüfen, denn die Bilder sollten ja beide existieren.

Selbst wenn `findContours()` das Array verändern *würde*, macht ``thresh.copy()`` keinen Sinn, weil das Array sonst nirgends verwendet wird.

Zwischenstand (ungetestet):

Code: Alles auswählen

import json
import os
from datetime import datetime as DateTime
from functools import partial
from pathlib import Path
from time import sleep

import cv2
import numpy as np
import pyautogui
from selenium import webdriver
from skimage.metrics import structural_similarity

SELF_PATH = Path(__file__).parent


def locate_image(image):
    return pyautogui.locateCenterOnScreen(SELF_PATH / image, confidence=0.9)


def click_image(image, clicks=1):
    x, y = locate_image(image)
    pyautogui.click(x, y, clicks=clicks, interval=0.25)


doubleclick_image = partial(click_image, clicks=2)


def make_screenshot(url, image_folder):
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument("--start-maximized")
    driver = webdriver.Chrome(options=chrome_options)
    driver.get(url)
    sleep(4)

    screenshot = pyautogui.screenshot()
    screenshot_path = (
        image_folder / f"Screenshot_{DateTime.now():%Y%m%d_%H%M%S}.png"
    )
    screenshot.save(screenshot_path)
    print(f"Screenshot gespeichert: {screenshot_path}")

    sleep(1)
    driver.quit()
    sleep(2)
    return screenshot_path


def compare_images(image1_path, image2_path, output_folder):
    images = list(map(cv2.imread, [image1_path, image2_path]))
    score, diff = structural_similarity(
        *(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) for image in images),
        full=True,
    )
    contours, _ = cv2.findContours(
        cv2.threshold(
            (diff * 255).astype("uint8"),
            0,
            255,
            cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU,
        )[1],
        cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE,
    )
    for x, y, w, h in map(cv2.boundingRect, contours):
        for image in images:
            cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)

    result_path = (
        output_folder / f"Vergleich_vom_{DateTime.now():%Y%m%d_%H%M%S}.png"
    )
    cv2.imwrite(result_path, np.concatenate(images, axis=1))
    return score, result_path


def main():
    with open("data.json", "rb") as file:
        config = json.load(file)

    images = config["images"]["url_screenshot"]
    image_ordner = config["images"]["folders"]

    for key, url in images.items():
        image_folder = Path(image_ordner[key]).expanduser()
        screenshot_before_path = make_screenshot(url, image_folder)

        click_image(images["chrome"])
        print("Öffne Chromebrowser")
        sleep(1)
        click_image(images["double_arrows"])
        print("Benutze Doppelpfeile oben rechts")
        sleep(1)
        
        website_image = images["website"][key]
        try:
            locate_image(website_image)
            print("erstes Bild gefunden")
            sleep(1)
            click_image(website_image)
            print("Öffne die Webseite")
        except pyautogui.ImageNotFoundException:
            try:
                print("erste Bild nicht gefunden, da kein Fullscreen")
                doubleclick_image(images["fullscreen"])
                sleep(1)
                click_image(website_image)
                print("Öffne die Webseite")
                sleep(1)
            except pyautogui.ImageNotFoundException:
                try:
                    click_image(website_image)
                    print("Öffne die Webseite")
                except pyautogui.ImageNotFoundException:
                    sleep(1)
                    click_image(website_image)

        sleep(1)

        try:
            click_image(images["bitwarden"])
            print("Öffne Bitwarden")
        except pyautogui.ImageNotFoundException:
            click_image(images["bitwarden2"])
            print("Öffne Bitwarden")

        sleep(1)
        click_image(images["zugangsdaten"][key])
        print("Benutze Zugangsdaten")
        sleep(2)
        click_image(images["login"])
        print("Klicke auf Login... bitte Yubikey verwenden")
        sleep(10)
        click_image(images["components"])
        print("Öffne Komponenten")
        sleep(1)
        click_image(images["akeeba"])
        print("Öffne Akeeba Backup")
        sleep(1)
        click_image(images["control_panel"])
        print("Öffne Controlpanel")
        sleep(1)
        click_image(images["start"])
        print("Beginne mit dem Backup")
        sleep(5)

        while True:
            try:
                locate_image(images["back_control_panel"])
                break
            except pyautogui.ImageNotFoundException:
                print("Update noch im Gange...")
                sleep(5)

        sleep(3)
        click_image(images["back_control_panel"])
        sleep(3)
        click_image(images["yoomla_home"])
        sleep(3)

        try:
            locate_image(images["green_star"])
            green_star = True
        except pyautogui.ImageNotFoundException:
            print("Sieht aus als müssten Updates gemacht werden.")
            green_star = False

        sleep(3)

        if green_star:
            print("updates sind akutell")
            click_image(images["green_star"])
            sleep(5)
            click_image(images["yoomla_home"])
        else:
            print("müssen aktualisiert werden")
            click_image(images["red_star"])
            sleep(3)
            while True:
                try:
                    click_image(images["checkbox"])
                    sleep(3)
                    click_image(images["update_btn"])
                    sleep(15)
                    click_image(images["yoomla_home"])
                    break
                except pyautogui.ImageNotFoundException:
                    print("warte auf weiterleitung....")
                    sleep(5)

        sleep(3)
        click_image(images["close_window"])
        sleep(3)

        screenshot_after_path = make_screenshot(url, image_folder)
        similarity_score, result_path = compare_images(
            screenshot_before_path,
            screenshot_after_path,
            Path(folders[key]).expanduser(),
        )
        print(f"Ähnlichkeitsindex (SSIM): {similarity_score}")
        print(f"Vergleich gespeichert: {result_path}")


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten