2024-02-24

QWebEnginePage のコンテクスト・メニュー

PySide (Qt for Python) は、Qt(キュート)の Python バインディングで、GUI などを構築するためのクロスプラットフォームなライブラリです。Linux/X11, macOS および Microsoft Windows をサポートしています。配布ライセンスは LGPL で公開されています。

QWebEngineView に表示されたウェブサイト上を右クリックするとコンテクスト・メニューが表示されます。メニューの中で、Back / Forward / Reload については機能が付いていますが、残る Save pageView page source については(少なくとも試した PySide6 のバージョンでは)何も反応がありません。

今回のテーマ
  • QWebEngineView で読み込んだ URL は、QWebEnginePage に表示されます。
  • ここに表示されたウェブサイト上で、右クリックすると表示されるコンテクスト・メニュー(下記)の Save pageView page source を利用します。

なお、本サンプルで使用しているウェブサイトは、下記を利用しています。

下記の OS 環境で動作確認をしています。

Fedora Workstation 39 x86_64
Python 3.12.1
PySide6 6.6.2

サンプルを以下に示します。

qt_webenginepage_3.py

このサンプルの実行例を以下に示しました。

qt_webenginepage_3.py の実行例

サンプルの説明

Save page

参考サイト [2]PySide6.QtWebEngineCore.QWebEnginePage.WebAction の説明によると、

定  数説  明
QWebEnginePage.SavePage
(QWebEnginePage.WebAction.SavePage)
Save the current page to disk. MHTML is the default format that is used to store the web page on disk. Requires a slot for downloadRequested() .
[参考訳]
現在のページをディスクに保存します。MHTML は、Web ページをディスクに保存する際のデフォルトのフォーマットです。downloadRequested() のスロットが必要です。

downloadRequested() のスロットが必要?

具体的に何をするのかピンとこなかったのですが、参考サイト [1] にズバリ知りたかったことが記載されていましたので、参考にさせていただきました。

class Example(QWebEngineView):
    def __init__(self, url: QUrl):
        super().__init__()
          :
          :
        self.page().profile().downloadRequested.connect(
            self.on_download_requested
        )

on_download_requested メソッドでは、最初に念のため self.pageAction(QWebEnginePage.WebAction.SavePage) が有効になっているか確認しています。

    def on_download_requested(self, download: QWebEngineDownloadRequest):
        action: QAction = self.pageAction(QWebEnginePage.WebAction.SavePage)
        if not action.isEnabled():
            return

        # Save page as single HTML
        url_path = download.url().path()
        if url_path == '/':
            url_path = 'index.html'
        suffix = QFileInfo(url_path).suffix()
        path, _ = QFileDialog.getSaveFileName(
            self, 'Save File', url_path, '*.' + suffix
        )
        if path:
            download.setSavePageFormat(
                QWebEngineDownloadRequest.SavePageFormat.SingleHtmlSaveFormat
            )
            download.setDownloadFileName(path)
            download.accept()

QWebEngineDownloadRequest クラスの使い方、あるいはそのインスタンス download の扱い方については、試行錯誤をしている状態です。とりあえず、表示されている HTML の内容が保存されることで良しとしています。🙇🏻

View page source

参考サイト [2]PySide6.QtWebEngineCore.QWebEnginePage.WebAction の説明によると、

定  数説  明
QWebEnginePage.ViewSource
(QWebEnginePage.WebAction.ViewSource)
Show the source of the current page in a new tab. Requires implementation of createWindow() or newWindowRequested() .
[参考訳]
現在のページのソースを新しいタブに表示します。createWindow() または newWindowRequested() の実装が必要です。

これもなんだかよく判らなかったのですが、とにかく createWindow メソッドを実装(オーバーライド)してテストしてみました。すると、コンテクスト・メニューの View page source を選択すると、確かにこのメソッドが実行されることを確認できました。

この createWindow メソッドが呼び出されるのは、ソースを表示したい時だけではないかもしれないので、まず self.pageAction(QWebEnginePage.WebAction.ViewSource) が有効になっているかどうかを確認しています。なお、HTML ソースの内容を QTextEdit などに表示した方が実用的ですが、ここでは単に print_html メソッドで標準出力しています。

    def createWindow(self, wwtype: QWebEnginePage.WebWindowType):
        action: QAction = self.pageAction(QWebEnginePage.WebAction.ViewSource)
        if not action.isEnabled():
            return
        # Just STDOUT
        self.page().toHtml(self.print_html)
    @staticmethod
    def print_html(html: str):
        print(html)

参考サイト

  1. python - How to download csv file with QWebEngineView and QUrl - Stack Overflow [2019-05-03]
  2. QWebEnginePage - Qt for Python
  3. QWebEngineView - Qt for Python
  4. QWebEngineDownloadRequest - Qt for Python

下記の動画では PyQt6 を利用しており、PySide6 ではありませんが大部分が同じなので参考になります。

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



このエントリーをはてなブックマークに追加

0 件のコメント: