2022/04/24(日) [n年前の日記]
#1 [python] PyAutoGUIを少しだけ試用
Python + PyAutoGUI でも操作の自動化ができるという話をどこかで見かけたので手元の環境で少し試用。
環境は Windows10 x64 21H2 + Python 3.9.12 64bit。
環境は Windows10 x64 21H2 + Python 3.9.12 64bit。
◎ インストール。 :
インストールは以下。
また、以下のモジュールも依存関係でインストールされた。
pip install pyautoguiPyAutoGUI 0.9.53 がインストールされた。
また、以下のモジュールも依存関係でインストールされた。
- MouseInfo 0.1.3
- PyGetWindow 0.0.9
- PyMsgBox 1.0.9
- pyperclip 1.8.2
- PyRect 0.2.0
- PyScreeze 0.1.28
- pytweening 1.0.4
◎ PDFの自動翻訳をしやすくする処理が書けた。 :
色々試していたところ、昨日、AutoIt を使って作成したスクリプトと似たような処理を、PyAutoGUI でも書けた気がする。
_英文PDFの自動翻訳をAutoIt3を使って少し快適にした
_04_copypaste.py
後は、このPythonスクリプトを、何かしらのランチャーに登録して起動できるようにすれば、1クリックでPDF上の選択テキストを自動翻訳できるのではないかな…。
一応、tkinter も使って、GUI版も書いてみた。
_05_copypaste_gui.pyw
実行するとGUIウインドウとボタンが表示されるので、ランチャーに登録等をしなくても使えるかもしれない。
_英文PDFの自動翻訳をAutoIt3を使って少し快適にした
_04_copypaste.py
import pyautogui as ag
import pygetwindow as gw
import pyperclip
import sys
import time
pdfviewer = "Reader DC"
deepl = "DeepL "
def activate_window(w):
"""Activate appli window."""
try:
w.activate()
except Exception:
w.minimize()
w.restore()
time.sleep(0.35)
def get_window(name):
hwnds = gw.getWindowsWithTitle(name)
w = None
if hwnds != []:
w = hwnds[0]
else:
print("Error: Not found %s" % name)
return w
def main():
w = get_window(pdfviewer)
if w is None:
sys.exit()
activate_window(w)
ag.hotkey("ctrl", "c")
time.sleep(0.25)
# replace CRLF to space
txt = pyperclip.paste()
newtxt = " ".join(txt.splitlines())
# newtxt = txt.replace("\n", " ")
pyperclip.copy(newtxt)
# print(newtxt)
w = get_window(deepl)
if w is None:
sys.exit()
activate_window(w)
ag.hotkey("ctrl", "a")
time.sleep(0.25)
ag.hotkey("delete")
time.sleep(0.25)
ag.hotkey("ctrl", "v")
time.sleep(0.25)
if __name__ == '__main__':
main()
後は、このPythonスクリプトを、何かしらのランチャーに登録して起動できるようにすれば、1クリックでPDF上の選択テキストを自動翻訳できるのではないかな…。
一応、tkinter も使って、GUI版も書いてみた。
_05_copypaste_gui.pyw
実行するとGUIウインドウとボタンが表示されるので、ランチャーに登録等をしなくても使えるかもしれない。
◎ ウインドウのアクティブ化でハマった。 :
これは PyAutoGUI というより PyGetWindow の問題っぽいけど…。Windows10 x64 21H2上では、既に起動しているアプリのウインドウをアクティブにできないことに気づいた。.activate() を呼ぶと、タスクバー上のアプリアイコンは点滅するものの、アプリウインドウが最前面になってくれない。エラーを吐く。
以下の、最大化、最小化は動いたから、ウインドウのID?を取得し損ねているわけではないのだろう…。
ググったところ、「Windows上ではアプリウインドウのアクティブ化はできないから、最小化+最大化で目的を果たせ」という話も見かけた。AutoIt と比べると厳しいな…。
一応、以下の投稿によると、最小化+復元すれば目的が果たせるらしい。
_.activate() sometimes throw error - Issue #31 - asweigart/PyGetWindow - GitHub
_Activate does not work - Issue #36 - asweigart/PyGetWindow - GitHub
_When using IPython, window.activate() raises error. - Issue #29 - asweigart/PyGetWindow - GitHub
Python 3.9.12 (tags/v3.9.12:b28265d, Mar 23 2022, 23:52:46) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> import pyautogui as ag
>>> import pygetwindow as gw
>>> w = gw.getWindowsWithTitle("Chrome")[0]
>>> w.activate()
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
w.activate()
File "C:\Python\Python39-64\lib\site-packages\pygetwindow\_pygetwindow_win.py", line 246, in activate
_raiseWithLastError()
File "C:\Python\Python39-64\lib\site-packages\pygetwindow\_pygetwindow_win.py", line 99, in _raiseWithLastError
raise PyGetWindowException('Error code from Windows: %s - %s' % (errorCode, _formatMessage(errorCode)))
pygetwindow.PyGetWindowException: Error code from Windows: 0 - この操作を正しく終了しました。
>>>
以下の、最大化、最小化は動いたから、ウインドウのID?を取得し損ねているわけではないのだろう…。
>>> w.minimize() >>> w.maximize()
ググったところ、「Windows上ではアプリウインドウのアクティブ化はできないから、最小化+最大化で目的を果たせ」という話も見かけた。AutoIt と比べると厳しいな…。
一応、以下の投稿によると、最小化+復元すれば目的が果たせるらしい。
_.activate() sometimes throw error - Issue #31 - asweigart/PyGetWindow - GitHub
_Activate does not work - Issue #36 - asweigart/PyGetWindow - GitHub
_When using IPython, window.activate() raises error. - Issue #29 - asweigart/PyGetWindow - GitHub
>>> w.minimize() >>> w.restore()
◎ 目標のアプリウインドウを間違えてしまう問題。 :
スクリプト作成中に、間違ったアプリウインドウを取得されてしまってハマった。ウインドウタイトルに「DeepL」という文字列を含んだ他のアプリがあると、そのアプリに文字列を貼り付けようとしてしまう。今回は、「copypaste_deepl.py」という名前のファイルを Visual Studio Code (vscode) で編集しながら動作確認していたら、vscode上のソースを全部消されてしまって焦った…。
アプリウインドウを、ウインドウタイトルだけで探すのはちょっと問題があるようだなと…。
でもまあ、とりあえず今回は、"DeepL" じゃなくて "DeepL " でウインドウタイトルを検索させれば誤魔化せるかな…。
アプリウインドウを、ウインドウタイトルだけで探すのはちょっと問題があるようだなと…。
でもまあ、とりあえず今回は、"DeepL" じゃなくて "DeepL " でウインドウタイトルを検索させれば誤魔化せるかな…。
◎ 改行コードの置換で悩んだ。 :
クリップボード内の、改行コードを複数含んだ文字列に対して、改行コードをスペースに置換するあたりでハマった。replace() を使ったら、何故か上手く置換できなくて…。
とりあえず、splitlines() と join() でどうにかしてみたけれど…。replace() では処理できないのだろうか…?
もしかして、"\n" と "\r\n" が混ざってしまっているのかな。
以下のページによると、改行コードの種類が不明な場合は .splitlines() と .join() を使うのもアリ、らしい。であれば、これでもいいのかな…。
_Pythonで改行を含む文字列の出力、連結、分割、削除、置換 | note.nkmk.me
とりあえず、splitlines() と join() でどうにかしてみたけれど…。replace() では処理できないのだろうか…?
# replace CRLF to space
txt = pyperclip.paste()
newtxt = " ".join(txt.splitlines())
pyperclip.copy(newtxt)
もしかして、"\n" と "\r\n" が混ざってしまっているのかな。
以下のページによると、改行コードの種類が不明な場合は .splitlines() と .join() を使うのもアリ、らしい。であれば、これでもいいのかな…。
_Pythonで改行を含む文字列の出力、連結、分割、削除、置換 | note.nkmk.me
[ ツッコむ ]
以上、1 日分です。