( endi123 | 2020. 02. 25., k - 15:46 )

Az alábbi módosítás sztem megoldja a problémát, lementi amit le lehet. Általánosságban a probléma hogy a mai weboldalak többségében js vezérli a betöltéseket (lazy loading, on-demand loading), ezért az "oldal betöltődése kész" esemény nehezen értelmezhető. Új resource betöltődése a LoadEvent.FINISHED esemény után! is történhet, szerencsére a webkit-et használó programban követhető az oldalhoz tartozó resource-ok betöltődési folyamata. Erre épül a következő módosítás (alapja az első hozzászólásom ), amely nem csinál képernyőmentést rögtön a LoadEvent.FINISHED után, ehelyett megvárja resource-ok betöltődését is.

Ahogy korábban most is hozzáadjuk a GLib-et az import-okhoz:

from gi.repository import Gtk, Gdk, GLib, WebKit2

A Browser osztályt egészben közlöm:

class Browser(base):
    def __init__(self, uri):
        super(Browser, self).__init__()
        
        self.webview = WebKit2.WebView.new_with_context(ctx)
        self.webview.connect("load-changed", self.on_load_changed)
        
        # Uj sorok
        self.timer_ms = 500
        self.resource_count_total = 0
        self.resources_loading_set = set()
        self.webview.connect("resource-load-started", self.on_resource_load_started)
        
        self.webview.load_uri(uri)
        self.add(self.webview)

        self.connect("destroy", Gtk.main_quit)
        self.set_size_request(render_width, 600) # set minimum size allowed

        self.set_title("Bongeszo - " + uri)
        self.show_all()
    
    def restart_timer(self):
        self.remove_timer()
        
        # Start timer only if the page is "loaded" and all resource load is finished
        if not self.webview.props.is_loading and len(self.resources_loading_set) == 0:
            self.timer_id = Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, self.timer_ms, self.on_timeout)
    
    def remove_timer(self):
        print("\t\t\t\t\t\t\t\t(resources loading: ", len(self.resources_loading_set), ", webview loading: ", self.webview.props.is_loading, ")", sep="")
        
        if hasattr(self, "timer_id"):
            GLib.source_remove(self.timer_id)
            del self.timer_id
            
    # WebView events
    
    def on_resource_load_started(self, web_view, resource, request):
        print("Resource load STARTED :", resource.get_uri())
        resource.connect("finished", self.on_resource_finished)
        if resource.get_response() is None:
            self.resources_loading_set.add(resource)
        self.remove_timer()
        self.resource_count_total += 1
        
    def on_resource_finished(self, resource):
        print("Resource load FINISHED:", resource.get_uri())
        self.resources_loading_set.discard(resource)
        self.restart_timer()
        
    def on_load_changed(self, web_view, load_state):
        print("\nLoad-state:", load_state, "\n")
        self.restart_timer()
    
    def on_timeout(self, *args):
        print("Resources loaded total:", self.resource_count_total)
        print("No load activity for", self.timer_ms, "ms, taking snapshot ...")
        self.webview.get_snapshot(WebKit2.SnapshotRegion.FULL_DOCUMENT, snapshot_opts, cancellable=None, callback=self.on_snapshot_finish)
        return GLib.SOURCE_REMOVE
    
    def on_snapshot_finish(self, web_view, result):
        print("Snapshot ready")
        cairo_surf = web_view.get_snapshot_finish(result)
        cairo_surf.write_to_png(dst_png_path)
        print("Snapshot saved to", dst_png_path)
        self.close()

A megértéséhez talán annyi elég, hogy ha a WebKit2.LoadEvent.FINISHED megvolt, és az utolsó resource is betöltődött, akkor elindít egy timer-t, amely self.timer_ms = 500 ideig vár. Ha a várakozás alatt új resource betöltés indul el, akkor a timer-t lelövi, később a betöltés befejezésekor újraindítja. Ha megszakítás nélkül lefut a timer, akkor menti a képernyőt és kilép.

Megjegyzés: a js lusta (kép)betöltést erősen használó oldalak, mint a youtube csak akkor töltenek be bizonyos képeket, ha lefelé görgeted az oldalt, sőt a görgetést figyelve akár bővítik is az oldalt. Ilyen esetek részben kezelhetőek azzal hogy a self.set_size_request(render_width, 600) sorban növeljük a 600-as height-et pár ezerre, vagy meg kell írni az szimulált (végig)görgetést.

Érdekesség, hogy a https://hup.hu cimlapjához a böngészőink 140 db resource-ot töltenek le, sok a google és a twitter. Itt a log vége:

Resource load STARTED : https://ton.twimg.com/tfw/assets/news_stroke_v1_78ce5b21fb24a7c7e528d22…
Resource load FINISHED: https://ton.twimg.com/tfw/assets/news_stroke_v1_78ce5b21fb24a7c7e528d22…
Resources loaded total: 140
No load activity for 500 ms, taking snapshot ...
Snapshot ready
Snapshot saved to hup.png