Rzezimioszek / eKW-pobieracz

Program służący do masowego pobierania ksiąg wieczystych z serwisu ekw.ms.gov.pl
162 stars 38 forks source link

Brak obsługi wyjątków przeglądarki #6

Open tisher2 opened 2 months ago

tisher2 commented 2 months ago

Program nieprawidłowo interpretuje wyjątki obsługi przeglądarki, tj wywala przy zaniku Internetu, przedwczesnym wyłączeniu przeglądarki, tymczasowym odrzuceniu połączenia i innych nie związanych z analizą wczytywanej strony.

Wykonałem takie bardzo kalekie rozwiązanie i jakoś to działa, ale na pewno można to zrobić lepiej.

from selenium.common.exceptions import (
    TimeoutException, WebDriverException, NoSuchElementException
)
from urllib3.exceptions import MaxRetryError, NewConnectionError
import time

def safe_quit_browser(browser):
    """Bezpieczne zamknięcie przeglądarki."""
    if browser:
        try:
            browser.close()
            browser.quit()
        except Exception as e:
            print(f"Błąd podczas zamykania przeglądarki: {e}")

def save_kw_to_pdf(value: str):
    save_path = win.lineSave.text()
    pdf_bg = win.chBg.isChecked()

    zupelna = False
    to_merge = []
    merge = win.chMerge.isChecked()

    gen_err(f"{value}\t- Wprowadzona wartość")

    max_retries = 5
    retries = 0
    browser = None

    while retries < max_retries:
        try:
            kw = value.split('/')

            if 2 <= len(kw) < 3:
                value = win.correct_kw_number(kw[0], kw[1])
                kw = value.split('/')
                gen_err(f"{value}\t- Poprawiono cyfrę kontrolną")

            if win.chSkip.isChecked():
                ext_list = [str(Path(p).stem)[0:16] for p in os.listdir(save_path)]
                if value.replace('/', '.') in ext_list:
                    return

            browser = get_driver(win.chImg.isChecked())
            browser.get('https://przegladarka-ekw.ms.gov.pl/eukw_prz/KsiegiWieczyste/wyszukiwanieKW')

            time.sleep(1)  # Czekaj na załadowanie strony

            insert_kw_number(browser, kw)

            time.sleep(1)  # Czekaj na załadowanie wyników

            if win.save_raport or win.save_csv:
                info = get_dictionary(browser)
                path_without_ext = f"{save_path}/{value.replace('/', '.')}"
                if win.save_raport:
                    save_json(info, path_without_ext)
                if win.save_csv:
                    save_csv(info, f"{save_path}/")

            if not win.save_pdf and not win.save_txt and not win.save_html and not win.chJSON1o:
                safe_quit_browser(browser)
                return

            # Sprawdzenie i próba pobrania
            try:
                elem = browser.find_element(By.NAME, 'przyciskWydrukZwykly')
                elem.send_keys(Keys.RETURN)
            except NoSuchElementException:
                zupelna = True
                err = f"{value}\t- Treść zwykła wydruku niedostępna dla"
                gen_err(err)
                break  # Wyjście z pętli, przejście do obsługi treści zupełnej

            break  # Wszystko przebiegło pomyślnie, wyjście z pętli

        except (TimeoutException, WebDriverException, MaxRetryError, NewConnectionError) as e:
            # Błędy sieciowe lub przeglądarki
            retries += 1
            gen_err(f"Błąd przeglądarki lub sieci: {str(e)}. Ponawianie próby {retries}/{max_retries}...", log=True)
            time.sleep(10)  # Poczekaj przed ponowną próbą
            safe_quit_browser(browser)

            if retries == max_retries:
                gen_err(f"Przekroczono maksymalną liczbę prób pobierania danych dla {value}.", write=True)
                return

    # Drugi blok try/except dla obsługi wyjątków specyficznych dla treści księgi
    try:
        if zupelna:
            if win.chError.isChecked():
                elem = browser.find_element(By.NAME, 'przyciskWydrukZupelny')
                elem.send_keys(Keys.RETURN)
                gen_err(f"{value}\t- Pobieranie treści zupełnej")
            else:
                err = f"{value}\t- Błąd pobierania treści zupełnej księgi"
                gen_err(err, write=True)
                safe_quit_browser(browser)
                return
    except Exception as e:
        err = f"{value}\t- Błąd pobierania księgi: {str(e)}"
        gen_err(err, write=True)
        safe_quit_browser(browser)
        return

    try:
        path_without_ext = f"{save_path}/{value.replace('/', '.')}"
        t_s = 1

        if win.ch1o.isChecked():
            time.sleep(t_s)
            to_merge.append(save_page(browser, "Dział I-O", path_without_ext, 1))

        if win.ch1s.isChecked():
            time.sleep(t_s)
            to_merge.append(save_page(browser, "Dział I-Sp", path_without_ext, 1))

        if win.ch2.isChecked():
            time.sleep(t_s)
            to_merge.append(save_page(browser, "Dział II", path_without_ext, 2))

        if win.ch3.isChecked():
            time.sleep(t_s)
            to_merge.append(save_page(browser, "Dział III", path_without_ext, 3))

        if win.ch4.isChecked():
            time.sleep(t_s)
            to_merge.append(save_page(browser, "Dział IV", path_without_ext, 4))

        gen_err(f"{value}\t- Pobrano księgę")
    except Exception as e:
        err = f"{value}\t- Błąd pobierania wybranych działów księgi: {str(e)}"
        gen_err(err, write=True)
        safe_quit_browser(browser)
        return

    finally:
        safe_quit_browser(browser)

    try:
        if win.save_pdf and merge and len(to_merge) > 0:
            gen_err(f"{value}\t- Łączenie pojedynczych działów KW w jeden plik", log=True)
            out_pdf = pypdf.PdfWriter()
            dst_path = f"{save_path}/{value.replace('/', '.')}.pdf"

            for tm in to_merge:
                src_pdf = pypdf.PdfReader(tm)
                out_pdf.append_pages_from_reader(src_pdf)

            with open(dst_path, "wb") as file:
                out_pdf.write(file)

            gen_err(f"{value}\t- Usuwanie pojedynczych działów KW", log=True)
            for tm in to_merge:
                os.remove(tm)

    except Exception as e:
        err = f"{value}\t- Błąd łączenia działów księgi: {str(e)}"
        gen_err(err, write=True)
Rzezimioszek commented 2 months ago

Fajnie to rozwiązałeś, dodałem to rozwiązanie do trybu zwykłego oraz pobierania turbo i w obu działa świetnie. Ogólnie jestem w trakcie zmiany UI na oparte na FLET i związku z tym będe przebudowywać to jak działa program, natomiast wersji opartej na QT się nie pozbywam i zrobiłem branch Legacy, gdzie umieściłem twój pomysł w wersji 1.2.01. Wielkie dzięki za kod i pomysł, napewno pomoże to nie tylko mnie, ale też osobą korzystającym z programu.

tisher2 commented 2 months ago

Najlepiej jakby nowy program nie wyłączał przeglądarki tylko operował na otwartym oknie, można wtedy zejść z 14sek przetwarzania zapytania nawet do 8sek łącznie z zapisem :)

SarJin91 commented 2 months ago

@tisher2 na jednym oknie blokuje po kilku pobraniach, tylko zamykanie przeglądarki powoduje że nie blokuje.