Playwrightを使って、note・X・Instagram・Bluesky・Tumblr・Amazonアソシエイト・YouTubeの操作を自動化しています。実際に運用してみて詰まった箇所と、その原因をまとめます。
1. headlessだと弾かれるサービスがある
Amazonアソシエイトの成果レポートを自動取得しようとして、4回連続で失敗しました。ログには毎回こう出ます。
[ERROR] ログインが切れています
実際にはログインは切れていませんでした。headless=Trueのときだけログイン画面に強制送還されていたのです。同じブラウザプロファイルのままheadless=Falseにすると、成果ページがそのまま開きました。
教訓は「ログインが切れています」と読めるエラーを鵜呑みにしないこと。画面ありで一度確かめてから判断してください。
2. has-text は部分一致なので危険
Playwrightのhas-text()は部分一致です。これで2回実害が出ました。
button:has-text("保存")が「下書き保存」を掴んだhas_text("追加")が「追加済」を掴み、再実行で登録を解除してしまった
かといって:text-is()は子要素の文字を見ないため、アイコン付きボタンでは使えません。結局、候補を列挙してinner_text().strip()で突き合わせる方式に落ち着きました。
loc = page.locator(f'button:has-text("{label}")')
for i in range(min(loc.count(), 8)):
b = loc.nth(i)
if b.is_visible() and b.inner_text().strip() == label:
b.click(); break
3. UIは予告なく変わる
noteのフォロー解除は、以前は「フォロー中」を押すと確認ダイアログが出る作りでした。これがドロップダウンメニューに変わり、メニュー内の「フォロー解除」を選ばないと外れなくなりました。
厄介だったのはエラーにならなかったことです。ボタンは押せているので処理は「成功」で終わり、実際には1件も解除されていませんでした。
対策は2つです。
- 操作後に状態が変わったかを必ず確認する(押せた≠変わった)
- 0件でも件数を数字でログに残す。「対象なし」とだけ書いていたため、3日間ゼロだったことに気づけませんでした
4. 無限スクロールのページで終了条件を間違えた
「ページの高さが変わらなくなったら終了」という条件を書いたところ、無限スクロールのページでは永久に成立せず、2時間の実行時間上限まで走り続けました。
正しくは「新しい対象が一定回数見つからなかったら終了」です。高さではなく成果で判定してください。修正後は36分で正常終了しました。
5. ログインセッションの持ち運びはプロファイル丸ごとにしない
ブラウザプロファイルは706MBありました。別のサーバーへ移すには重すぎます。
Playwrightのstorage_stateを使えば、CookieとlocalStorageだけを4KBのJSONで書き出せます。移行はこちらが実用的です。
まとめ
- headlessで弾かれるサービスがある。失敗時はまず画面ありで確認する
- has-textは部分一致。inner_textで完全一致を取る
- 押せた≠変わった。操作後に状態を確認し、0件も数字で残す
- 無限スクロールは「高さ」ではなく「成果」で終了判定する
- セッションの持ち運びはstorage_state(4KB)




