Amazonアソシエイトの成果レポートを自動取得するスクリプトが、4回連続で同じ理由で失敗しました。ログには毎回「ログインが切れています」。でも実際にはログインは切れていませんでした。原因はheadless=Trueだったことです。
4回失敗して、一度も成功していなかった
Amazonアソシエイトの成果レポートを自動で取ってくるスクリプトを作りました。結果から言うと、作成してから4回とも同じ理由で失敗しており、一度も成功していません。
厄介だったのは、失敗の仕方が「それらしかった」ことです。ログには毎回、こう記録されていました。
ログインが切れています
このメッセージを見た時点で、私は原因を決めつけていました。セッションが飛んだのだろう、と。だから対処もその方向にしか向かいませんでした。ログイン状態を作り直す、プロファイルを確認する、待ち時間を延ばす。どれも的外れでした。
「ログインが切れています」というログを信じて、セッション周りばかりを疑い続けたこと。実際にはログインは切れていませんでした。エラーメッセージが指している方向と、本当の原因が違っていたのです。
headless=False にしたら、何事もなく開いた
手詰まりになって、最後に画面ありで動かしてみました。同じブラウザプロファイルのまま、headless=False に変えただけです。
成果ページがそのまま開きました。ログインは求められませんでした。
つまり、headless=True のときだけ、ログイン画面にリダイレクトされていたということです。ログインそのものは最初から生きていて、切れていたことは一度もありませんでした。
同じプロファイル、違う結果
| 条件 | 結果 |
|---|---|
| headless=True | ログイン画面にリダイレクト |
| headless=False(同一プロファイル) | 成果ページがそのまま表示 |
ブラウザプロファイルは変えていません。変えたのは headless の真偽値ひとつだけです。それだけで挙動が分かれました。
なぜそうなるのかは、私には分かっていません
ここは正直に書きます。headless のときだけリダイレクトされる仕組みが何なのか、私は特定できていません。
私が確認できたのは、次の事実だけです。
- headless=True だとログイン画面に飛ばされる
- headless=False だと成果ページが開く
- プロファイルは同一で、ログインは切れていない
- サービス側が何を見て判定しているのか
- headless を回避する確実な方法があるのかどうか
- 他のサービスでも同じことが起きるのかどうか
これらは分かっていません。推測で埋めることもできますが、それを書くと読んだ人が同じ落とし穴にはまるので、書きません。
「headless だとダメ」という事実を確認しただけで、回避策を見つけたわけではありません。私の環境では headless=False で運用する形に落ち着いています。それが正解かどうかは、まだ判断がついていません。
教訓:エラーメッセージを信じすぎない
この件で一番痛かったのは、時間の使い方を完全に間違えたことです。「ログインが切れています」と書いてあったので、ログインを疑いました。ログを読むという行為自体は正しいのに、そこから先の判断が固定されてしまいました。
もし2回目の失敗の時点で画面ありで開いていれば、その場で終わっていた話です。「ログインが切れている」と読めるエラーでも、まず画面ありで確認してから判断する。これが今回得た唯一で最大の教訓です。
headless で失敗したときの確認は、コードを直す前に headless=False にして自分の目で見ること。画面に何が表示されているかが分かれば、ログの文言に引きずられずに済みます。
私が今後やる順番
- 失敗ログを読む(ただし結論は出さない)
- 同じプロファイルのまま headless=False で再実行する
- 画面に実際に何が出ているかを目で確認する
- そこで初めて原因を判断する
順番を入れ替えただけですが、今回に限って言えば、これで4回分の失敗が防げたはずです。
headless=False に切り替えたら、成果ページがそのまま開きました。プロファイルの作り直しも、ログイン処理の追加も必要ありませんでした。
自動化を組む人へ
headless は便利です。画面を出さずに済むので、サーバー上でもバックグラウンドでも動かせます。ただ、headless であること自体がサービス側の挙動を変える場合がある、という可能性を頭の片隅に置いておく必要があります。少なくとも私が触ったこのケースでは、そうでした。
そして、エラーメッセージは親切なようでいて、こちらの思考を縛ります。今回の「ログインが切れています」は、私のスクリプトが出したログですが、その判定ロジックが見ていたのは「ログイン画面にいるかどうか」だったわけです。画面には確かにログインフォームが出ていた。だからログは間違っていない。ただ、その理由が私の想定と違っただけです。
- Amazonアソシエイトの成果レポート自動取得が4回連続で失敗し、成功は0回だった
- ログは毎回「ログインが切れています」だったが、実際にはログインは切れていなかった
- headless=True のときだけログイン画面にリダイレクトされていた
- 同じプロファイルのまま headless=False にすると、成果ページがそのまま開いた
- なぜ headless だけ弾かれるのか、その仕組みは特定できていない
- 「ログインが切れている」と読めるエラーでも、まず画面ありで確認してから判断すること

