質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

1回答

4572閲覧

tkinterのウインドウ内にwebブラウザを表示させたい

sutekinamori

総合スコア11

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2023/01/29 07:48

編集2023/01/29 12:17

前提

ヤフオクから取得した宛先データをクリックポストに入力するソフトを作っています。
pythonのseleniumで落札された商品一覧データを取得し、tkinterで開いたウインドウに、表示させ、クリックすると、クリックポストにその商品購入者の宛先が入力されます。

実現したいこと

seleniumでのスクレイピング時に開かれるwebブラウザをtkinterのウインドウ内に表示させたいです。

ウインドウの左側に取得した商品一覧。右側にスクレイピング実行中のwebブラウザ画面が表示されるようにしたいです。

ちなみにtkinterでなくても、上記の事が可能なやり方があれば教えていただきたいです。

試したこと

pywebviewやwebviewなどを使ってみたのですが思うように出来ませんでした。

pyqt5でオープンボタンを表示させて、クリックするとウインドウ内にブラウザを開くことが出来ました。
ただseleniumで開かれるブラウザを表示させる方法がわかりません。。

from PyQt5.QtCore import QUrl import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton from PyQt5.QtWebEngineWidgets import QWebEngineView class MainWindow(QWidget): def __init__(self): super().__init__() self.layout = QVBoxLayout() self.button = QPushButton("Open") self.browser = QWebEngineView() self.button.clicked.connect(self.open_browser) self.layout.addWidget(self.button) self.setLayout(self.layout) def open_browser(self): self.browser.load(QUrl("https://www.google.com")) self.layout.addWidget(self.browser) app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

残念ながら簡単な方法はなさそうです。
2つのトピックがあるので、個別に検討しましょう

  • GUI に外部プログラムのウィンドウを組み込む方法
  • selenium との連携

前者は、大抵のGUI ライブラリではサポートされておらず、
プラットフォーム毎に方法が異なります。

例: windows なら、win32API で、対象のウィンドウハンドルを所得して、
親となるウィンドウを、自分で作成したウィンドウに変更する。(win32 api の SetParent)
tkinter/windows であれば、winfo_id でウィンドウハンドルを所得出来ます。

Python でコードを書く場合、ctypes ライブラリを利用できますが、
プラットフォーム毎のネイティブのGUIの情報 C/C++ の知識が必須です。

※ wxPython/windows では、埋め込み技術である ActiveX/COM が使えるので
ActiveXに対応した、古い Internet Explorer の埋め込みなら対応しています。
お勧めはできませんが、情報として書き残しておきます。


selenium に関しては、ブラウザの挙動は利用するWebドライバーにより異なります。
Chromium 系であれば CEF (Chromium Embeded Framework)
Edge であれば、Microsoft Edge WebView2 API, filefox なら gecko 等

既存のライブラリで探してみて、Qt で使えそうなものにQtWebDriver がありましたが、
残念ながら、更新が数年前で止まっていて保守されていないようでした。
もし、自身で selenium のドライバーを作成されるなら、コード等は参考になるかもしれません。

どちらの方法も、簡単なコードでという規模ではないので、方針のみ提示とします。

ブラウザ組み込みに関しては、元々ブラウザのエンジン内でGUIを構築する
「cefpython」 を selenium で操作する方法を検討してみてはいかがでしょう。


他の、簡単に出来そうな代替案としては、質問の要点からは外れますが、

  • ウィンドウを並べて表示
  • スクレイピングした情報を所得し、GUI内で再整形して表示

ページ数が多いと手間かもしれませんが、ブラウザを埋め込むよりは簡単だと思います。

投稿2023/02/03 03:38

teamikl

総合スコア8681

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sutekinamori

2023/02/05 08:03 編集

回答ありがとうございます。簡単な方法は無いんですね。。。 windowsならwin32API で実装できそうですね。ちなみに私の環境はlinuxです。最初にOSを書くべきでした。すみません。 とりあえずは諦めて ・ウィンドウを並べて表示 ・スクレイピングした情報を所得し、GUI内で再整形して表示 で実装することにしました。 ちなみになんですが self.browser.setHtml(self.driver.page_source) このコードをseleniumの処理の合間に挟むことで外部ブラウザと同じ表示をpyqt5のウインドウ内に表示させることができました。 しかし、「データのサイズが大きすぎます。データを破棄します」とエラーが頻繁に発生します。 この原因と解決方法があれば教えて頂きたいです。
teamikl

2023/02/05 09:42 編集

使われているのは Chromium で setHtml は 2MB の制限があります。 https://doc.qt.io/qt-5/qwebengineview.html#setHtml これは大きなデータを送られた場合は、setHtml の実装で読み込むには不都合があるという、 ライブラリ側の意図的な制限なので、解決策は load 等、他の方法でページを読み込む事になります。 他の方法としては、ChromiumDriver であれば cefpython を操作するのと同様のアプローチ remote-debugging-port を指定して起動済ブラウザを操作するオプションが QWebEngineView 側でも対応してるので、この辺りの設定を試してみてはどうでしょう。
teamikl

2023/02/05 10:04

追記、仕組み的には出来そうだけど、QWebEngine で使われているのと同じバイナリを使うWebDriver を selenium 側でも使わないといけないので、単純にremote debugging port の設定だけとはいかなさそうです。 バイナリが完全に同じでないといけないのか、バージョン番号だけ合わせればよいのかは要検証。
sutekinamori

2023/02/07 00:19

2MBの制限があるんですね! chatgptに言われるがままにやっていたのですがちゃんと調べないとですね。。 いろいろな提案ありがとうございます。一番スムーズにできそうな方法は win32API を使ったやり方な気がしたのでwindowsのパソコンを買いました...!
teamikl

2023/02/07 10:24 編集

回答としては、 ChromeDriver を使って remote-debugging-port 経由で操作する方法が プラットフォームに依存しないので一番スマートな解決策だと思います。 win32APIの説明は簡潔に済ませましたが、スムーズにいくかどうかは保証ないです。 多分、ウィンドウの枠を消したり、 主に見た目の細かな部分で、様々な調整が必要になりそうなので、 別ウィンドウで並べた方が遥かに楽だったりします。 (Windowsで) win32api を使った外部ウィンドウ埋め込みの手順は、 1. selenium側でブラウザのPIDを調べる 2. PID から対象のウィンドウハンドルを調べる EnumWindows, GetProcessThreadId 3. 同一プロセス内にウィンドウハンドルは複数あるので、GetClassName 等で、対象のウィンドウを特定する。 4. 以上で得られるウィンドウハンドル (HWND) をGUIに埋め込む  tkinter なら winfo_id と win32api のSetParent,  qt なら QWindow.fromWinId, QWidget.createWindowContainer ChatGPTは、上手に活用できれば、本当に便利で、 Python から ctypes 経由で win32api を呼び出すには、 ヘッダを調べ適切な型を指定してと、実質 C/C++ の知識が必須だったのが、 「Pythonのctypesを使ってwin32api の XXX関数 を呼び出す方法を教えて」 と尋ねるだけで、実際に使えるサンプルコードを得られます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問