プログラミング日和
テンション高め
最近、コーヒーを飲むようになってからテンションが妙に高いんですよね。
ただ、歯医者に通い始めたので、できればコーヒーは控えたいところ。
そこで思い出したのが、タンスの奥で5年間眠っていたカフェイン錠剤。
「これ、まだ使えるんじゃ?」と思って引っ張り出してきて、試しに飲んでみました。
1錠200mgはさすがにビビるので、まずは半分に割って飲むことに。
——結果、効果は想像以上に強烈。
あの、身体がだるくて頭も重くて“しなってしまう”ような状態から、
一瞬で“背骨に鉄パイプを通された”みたいにシャキッとするんですよ。
自分でも「もう年齢で頭の回転が落ちてきたのかな…」なんて思い始めてたのに、
飲んだ瞬間、思考が爆発的に冴える感じ。
その勢いでプログラミングが楽しすぎて止まらない。
朝はAndroid、昼はPython、夜はRPAマクロ制作と、
完全に“狂ったように”PCに向かっています。(いやほんと狂ってます)
方眼紙マップエディタの再公開
公開停止にしたつもりは全然なかったのですが、どうやら“本人確認メールをスルーしていた”せいで、気づいたらアプリがPlayストアから削除されてしまっていました。
しかも、開発専用に作ったアカウントだったので通知にも気づかず…。
復旧までが、まあ大変でして。

結局、免許証の表裏の写真を送ることで何とか再公開できることになったのですが、
今は検索には引っかからず、リンクからしかアクセスできない状態です。
とはいえ、ありがたいことに、apkのバックアップを公開してくれているサイトがあったようで、どうやらまだ使ってくれている人がいるみたい。
ちょっとほっとしました。
それにしても、ソフトウェア名が商標登録されていそうで、名前を変えたほうが良いのかな…と思ったり。
さらに言うと、プロジェクト名が「myapplication1」なのもちょっと恥ずかしいですね(笑)
でも、あれこれ考えてみると、初めて作ったAndroidアプリにしては結構気合い入ってたんじゃないかな、なんて思います。
株価監視プログラム
最近ちょこちょこ作っている、Python製の株価監視プログラムなんですが、
気づけばいい感じにアップデートが進んでおります。

最初は Yahoo!ファイナンスのAPI を使って、海外のCME日経先物の価格を取ってたんですけど、
どうも国内の動きとズレがあってモヤモヤしてたんですよね。
「なんか他に方法ないかな〜」と試行錯誤してたら、意外と良い手段を発見しました。
それが selenium でページを開いてタグを読むだけ作戦。
リアルタイムで値が更新されるし、やってることは“普通にブラウザで見てるのと同じ”なので、
多分サイトにも変な負荷はかからないはず…たぶん。
それにしても ChatGPT が便利すぎる。
「10秒ごとに記録したいんだけど?」って聞けばしれっとサンプルコードを出してくるし、
「seleniumで◯◯したい」って言えば即答。
どんだけ有能なんだと…。
そんな感じで、今日も地味〜にコードを書きながら遊んでます。
Copilotの制限
ChatGPT も十分すごいんですけど、最近は GitHub Copilot のやばさにも驚かされてます。
書こうとしているコードを、こちらがタイプする前にスッ…と出してくるんですよ。
慣れないうちは「え、なんで分かったの?」ってちょっとゾワッとするレベル。
未来予知か。
で、楽しくなってそのままプログラミングしまくっていたら、気づいたら 使用制限に到達…。
次に使えるようになるのがまさかの 24日後。
長い。長すぎる。
月1500円なら課金してもいいかな〜と悩んでるんですが、
すでに ChatGPT に課金してるし、「まあこっちでも十分じゃ?」みたいな気持ちもあって、判断が揺れています。
あと、個人的に Codex の使い方がいまいちよく分かっていない。
触ればすごいのは分かるんだけど、どう活かすのが正解なのか、まだ掴めてません。
そんな感じで、今日もツールの便利さに翻弄されつつコードを書いてます。
RPAツールの制作
以前、Pythonで “UWSCっぽい自動操作ツール” を作ったって記事を書いたんですが、
最近ふと思い立ってそのツールを引っ張り出してきました。
で、何をしたかというと——マケスピ2に高速ログインするコードを作成。
画像認証の部分だけはさすがに手動なんですが、それ以外は全部自動化。
デスクトップに置いた「高速ログイン.bat」をダブルクリックするだけで、
約30秒後にはメイン画面までたどり着けます。めちゃ快適。
流れとしてはこんな感じ↓
- アプリ起動
- パスワード入力
- ログインボタンをクリック
- GMailを開く
- 認証メールを探して開く
- 認証画面を上端に移動&最前面へ
- ここで手動の画像認証(ここだけは人間の仕事)
- ポップアップ類を全部閉じる
- GMailを閉じる
- マケスピを最前面に戻す
という、ちょっとした“自動ログインマシン”です。
自分で作っておいてなんですが、めちゃくちゃ便利。
一度慣れると、もう手動でログインする気になれません…。
パスワード管理に関してもkeyringというモジュールを知ることができて勉強になりました。
APIキー類もここに登録すると良いですね
ソースコードは次のような感じ
# encoding: utf-8
from RPA import *
import keyring
import getpass
import os
def find_marketspeed2():
local = os.getenv("LOCALAPPDATA") # C:\Users\myname\AppData\Local
path = os.path.join(local, "MarketSpeed2", "Bin", "MarketSpeed2.exe")
if os.path.exists(path):
return path
return None
MARKET_SPEED_EXE = find_marketspeed2()
if MARKET_SPEED_EXE is None:
raise Exception("マーケットスピードのインストールパスが見つかりません。")
if __name__ == "__main__":
# OSのセキュアストレージに登録したログインパスワードを読み出し
SERVICE_NAME = "market_speed2"
USER_NAME = "login_password"
password = keyring.get_password(SERVICE_NAME, USER_NAME)
if password is None:
print("マーケットスピードのログインパスワードを一度だけ入力してください。")
password = getpass.getpass("Password: ") # 画面に表示されない形で入力
# OS のセキュアストレージに保存
keyring.set_password(SERVICE_NAME, USER_NAME, password)
print("パスワードを保存しました。次回以降は自動で読み込みます。")
# マーケットスピード2を起動してログインする
os.chdir(os.path.dirname(MARKET_SPEED_EXE))
os.startfile(MARKET_SPEED_EXE)
if ACTWIN("MARKETSPEED II ログイン", 30) == 0:
raise Exception("マーケットスピードの起動に失敗しました。")
# パスワードを入力してログインボタンを押す
RPA_INIT()
SLEEP(1)
TYPING(password)
SLEEP(0.1)
KEY('tab', 0.1)
KEY('tab', 0.1)
KEY('tab', 0.1)
KEY('enter', 2)
# GMailを開いてパスキーの認証コードを取得
WEB_OPEN('https://mail.google.com')
ACTWIN("受信トレイ", 30, True)
SLEEP(5)
KEY('f5')
CLICK_IMG_OFFSET("gazo_icon.png", 0, -30) # 添付画像アイコンの少し上をクリックしてメールを開く
SLEEP(2)
# 絵文字認証の画面をアクティブにして画面上端に移動
ACTWIN("絵文字認証", 30)
MOVE_WINDOW_Y("絵文字認証", 0)
# 起動時のダイアログ類を全て閉じる
CLOSE_WINDOW_NAME("パスキーでログインできます", 60)
CLOSE_WINDOW_NAME("MARKETSPEED II", 30)
CLOSE_WINDOW_NAME("新機能のご紹介", 30)
CLOSE_WINDOW_NAME("ホーム", 30)
CLOSE_WINDOW_NAME("お知らせ", 30)
# GMailを閉じる
ACTWIN("ログイン追加認証コード", 30, True)
SLEEP(1)
CTRLKEY('w')
# マーケットスピードをアクティブにする
ACTWIN("MarketSpeed2", 30)
USWCを意識して大文字の関数にしてます
RPA.pyの中身はこんな感じ(まだ作りかけで雑ですが)
import pyautogui
import win32gui
import win32com.client
import time
import subprocess
import os
import webbrowser
# 初期化
def RPA_INIT():
SET_CURDIR()
# カレントディレクトリを実行パスと同じフォルダにセットする
def SET_CURDIR():
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# マウス位置を取得
def MMV(x, y, ms=0):
pyautogui.moveTo(x, y, ms)
# マウス位置を取得
def MPOS():
return pyautogui.position()
# 指定座標をクリック
def CLICK(x=None, y=None):
if x is None or y is None:
pyautogui.click()
else:
pyautogui.click(x, y)
# 指定座標を右クリック
def RCLICK(x=None, y=None):
if x is None or y is None:
pyautogui.click(button="right")
else:
pyautogui.click(x, y, button="right")
# 指定座標をダブルクリック
def DBLCLICK(x=None, y=None):
if x is None or y is None:
pyautogui.click(clicks=2)
else:
pyautogui.click(x, y, clicks=2)
# 一時停止(秒)
def WAIT(t):
time.sleep(t)
# 一時停止(秒)
def SLEEP(t):
time.sleep(t)
# キーを押す
def KEY(key, wait=0):
pyautogui.press(key)
if wait > 0:
SLEEP(wait)
# 複数のキーを打つ
def TYPING(text):
pyautogui.write(text)
# シフトを押す
def DOWNSHIFT():
pyautogui.keyDown('shift')
# SHIFTを離す
def UPSHIFT():
pyautogui.keyUp('shift')
# Ctrlを押す
def DOWNCTRL():
pyautogui.keyDown('ctrl')
# Ctrlを離す
def UPCTRL():
pyautogui.keyUp('ctrl')
# Shift + Key
def SHIFTKEY(key):
pyautogui.hotkey('shift', key)
# Ctrl + Key
def CTRLKEY(key):
pyautogui.hotkey('ctrl', key)
# 画面上の画像をクリック
def CLICK_IMG(img):
pt = pyautogui.locateCenterOnScreen(img)
CLICK(pt[0], pt[1])
# 画面上の画像をダブルクリック
def DBLCLICK_IMG(img):
pt = pyautogui.locateCenterOnScreen(img)
if pt is not None:
DBLCLICK(pt[0], pt[1])
# 画像が見つかるまで待つ
def WAIT_IMG(img, timeout=10):
while(1):
pt = None
try:
pt = pyautogui.locateCenterOnScreen(img)
except:
pass
if pt is not None:
return pt
time.sleep(0.1)
timeout -= 0.1
if timeout <= 0:
break
return None
# 画像があるかどうか調べる
def FIND_IMG(img):
pt = pyautogui.locateCenterOnScreen(img)
if pt is not None:
return pt
else:
return None
# 画像をクリックするまで待つ
def WAIT_CLICK_IMG(img):
pt = WAIT_IMG(img)
CLICK(*pt)
def CLICK_IMG_OFFSET(img, x, y):
pt = WAIT_IMG(img)
CLICK(pt.x + x, pt.y + y)
# ウィンドウを最前面にする
def ACTIVE_WINDOW(hwnd):
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys('%')
win32gui.SetForegroundWindow(hwnd)
# 指定タイトルのウィンドウを最前面にする
def ACTWIN(name, timeout=0, flagPart=False):
if flagPart:
ACTWIN_NAME_PART(name, timeout)
else:
ACTWIN_NAME(name, timeout)
# 指定タイトルのウィンドウを最前面にする(名前一致)
def ACTWIN_NAME(name, timeout=10):
shell = win32com.client.Dispatch("WScript.Shell")
while(1):
hwnd = win32gui.FindWindow(None, name)
if hwnd != 0:
shell.SendKeys('%')
win32gui.SetForegroundWindow(hwnd)
return hwnd
time.sleep(0.1)
timeout -= 0.1
if timeout <= 0:
break
return 0
# 指定タイトルのウィンドウを最前面にする(名前の部分一致)
def ACTWIN_NAME_PART(name, timeout=10):
while True:
hwnd = FIND_WINDOW_PART(name)
if hwnd != 0:
ACTIVE_WINDOW(hwnd)
break
time.sleep(0.1)
timeout -= 0.1
if timeout <= 0:
break
# Shellコマンド実行
def EXEC(path, arg=""):
#win32api.ShellExecute(0, path, arg, None, ".", 0)
#RunAs(path, "", arg)
#ctypes.windll.shell32.ShellExecuteW(0, 0, path, arg, 0, 1)
subprocess.Popen([path, arg], shell=False)
# フォルダを開く
def OPEN_FOLDER(path):
subprocess.Popen(['explorer', path], shell=True)
# フォルダを開いて移動させる
def OPEN_FOLDER_PLACE(path, x, y, width, height):
name = os.path.basename(path)
hwnd = FIND_WINDOW(name)
if hwnd == 0:
OPEN_FOLDER(path)
else:
ACTIVE_WINDOW(hwnd)
hwnd = FIND_WINDOW_WAITING(name)
if hwnd != 0:
print(str(hwnd))
MOVE_WINDOW(hwnd, x, y, width, height)
# ウィンドウを探す
def FIND_WINDOW(name):
return win32gui.FindWindow(None, name)
# 特定のタイトルを含むウィンドウを探す
def FIND_WINDOW_PART(name):
def enum_handler(hwnd, result):
if win32gui.IsWindowVisible(hwnd):
title = win32gui.GetWindowText(hwnd)
if name in title:
result.append(hwnd)
result = []
win32gui.EnumWindows(enum_handler, result)
if len(result) > 0:
return result[0]
return 0
# ウィンドウが見つかるまで待つ
def FIND_WINDOW_WAITING(name, timeout=3):
while(1):
hwnd = FIND_WINDOW(name)
if hwnd != 0:
return hwnd
time.sleep(0.1)
timeout -= 0.1
if timeout <= 0:
break
return 0
# ウィンドウを移動させる
def MOVE_WINDOW(hwnd, x, y , width, height):
win32gui.MoveWindow(hwnd, x, y, width, height, True)
# ウィンドウのY座標を変更
def MOVE_WINDOW_Y(title, y):
hwnd = FIND_WINDOW_WAITING(title)
if hwnd == 0:
return
# 現在のウィンドウ位置とサイズを取得
rect = win32gui.GetWindowRect(hwnd)
x = rect[0]
width = rect[2] - rect[0]
height = rect[3] - rect[1]
# Y座標を 0 に固定して移動
win32gui.SetWindowPos(
hwnd,
None,
x, # X はそのまま
y, # Y を 0 に
width,
height,
4 # Z順は変更しない
)
# ウィンドウを閉じる
WM_CLOSE = 0x0010
def CLOSE_WINDOW(hwnd):
win32gui.PostMessage(hwnd, WM_CLOSE, 0, 0)
# WEBブラウザで指定URLを開く
def WEB_OPEN(url):
webbrowser.open(url)
# 指定タイトルのウィンドウを閉じる
def CLOSE_WINDOW_NAME(hwnd_name, timeout=10):
while True:
hwnd = FIND_WINDOW(hwnd_name)
if hwnd != 0:
CLOSE_WINDOW(hwnd)
break
time.sleep(0.1)
timeout -= 0.1
if timeout <= 0:
break自動操作系のスクリプトを扱っていて思うのですが、
やっぱり 「目的の画面がちゃんと表示されるまで待つ」処理を入れておくことって大切ですね。
これがあるだけで動作が安定しますし、使っていても安心感があります。
逆に、待ち処理が不十分だと、画面の切り替えに追いつけなくて変な動きをし始めたりして、どうしても不安定になりがちです。
画面を確認してから次のステップに進む——本当にシンプルなことなんですけど、
実際にはこれが“人が操作するときの自然な流れ”に近づけてくれるんですよね。
ちょっとした工夫ではあるものの、最終的な使い心地を大きく左右するポイントだなと改めて感じています。
おわりに
今回の記事も、最後は ChatGPT に軽く校正してもらいながら仕上げました。
プログラミングだけじゃなく、文章づくりやちょっとした生活の工夫まで、気づけばAIがいつもそばにいるような時代になりました。もう、“無い生活”には戻れません。
それに、自分の拙い文章でも ChatGPT にお願いすると、ふんわり読みやすい形に整えてくれるので本当に助かっています。「ブログ風にして」と一言添えて貼り付けるだけでいい手軽さも、めちゃくちゃありがたいポイントです。
たまに文体がブレたりもしますが、それも含めてAIらしい味として楽しんでいます。
そんなわけで、今日もテンション高めにプログラミング日和でした。
これからも、作って遊んで、また面白いネタができたら書いていこうと思います。

しゅごい
最近のコメント