自動投稿アプリDay14
Cursorで開発
今までReplitでバイブコーディングしていたから気づきにくかったですが、じっくりと対話しながら開発すると色々と見えてきますね。以下のようにステップバイステップで解決しています。
真っ白画面対策
前日お話しした真っ白について、ステルス実行というのをしたらサクッとうまくいきました!
(ちなみに以下のような技術です)
🕵️♂️ Playwrightのステルス実行とは?
1. ステルス実行は、自動操作していることをサイトにバレにくくする技術です。
2. 多くのWebサイトは、自動化ツールを検出してブロックします(bot対策)。
3. 代表的な検出ポイント:navigator.webdriver, ヘッドレス判定, Canvas情報など。
4. ステルス機能はこれらの値を偽装または削除して検出を回避します。
5. その結果、人が操作しているかのように見えるようになります。
6. Pythonでは stealth_sync(page) のようなコードで適用可能です。
7. CloudflareやVoicyなどの厳しいサイトにもログインできる可能性が高くなります。
8. 完璧ではありませんが、多くのサイトで成功率が大きく向上します。
9. ヘッドフル(画面表示あり)と併用するとより自然になります。
10. 自動化と検出回避を両立したいときの必須テクニックです。SPAでEmail/Passが見えない
input[type="password"]という形でHTMLのコンポネントがpasswordになっているものを取得するようにしています。そうすると失敗していました。
その代わりにメールアドレス入力欄にname="email"やplaceholder="メールアドレス”となっているものを選ぶようにしたらうまくいきました!
ログインボタンが見つからない(SNSのOAuthのみ見える)
以下のようにSNSでのログインは検出できますが、肝心のログインボタンが見つかりません。。。これはReplitでも同様に苦労していたエラーですね。
An error occurred: Locator.click: Error: strict mode violation: get_by_role("button", name="ログイン") resol
ved to 5 elements:
1) <button _ngcontent-ng-c1322362268="" class="login-button ng-star-inserted">…</button> aka get_by_role
("button", name="Googleでログイン") 2
) <button _ngcontent-ng-c1322362268="" class="login-button ng-star-inserted">…</button> aka get_by_role
("button", name="Appleでログイン") 3
) <button _ngcontent-ng-c1322362268="" class="login-button ng-star-inserted">…</button> aka get_by_role
("button", name="LINEでログイン") 4
) <button _ngcontent-ng-c1322362268="" class="login-button ng-star-inserted">…</button> aka get_by_role
("button", name="Facebookでログイン") 5
) <button _ngcontent-ng-c1322362268="" class="login-button ng-star-inserted">…</button> aka get_by_role
("button", name="Xでログイン")
Call log:
- waiting for get_by_role("button", name="ログイン")CursorがJavascript付きのHTMLを取得して解析してくれました。
HTMLで多くの場合Buttonタグでログインボタンが実装されていますが、ここはアンカータグを使っているようです。
(GoogleなどSNSはログインボタンでした。)
<a _ngcontent-ng-c3431788102="" id="login-button" class="btn btn-primary">ログイン</a>その後、このid “login-button“となっているところをクリックするように設定します。
そうしたらうまく入れるようになりました!🎉🎉🎉
(念の為、ユーザー画面から見えない情報はマスクしています)
新規作成に移動
ここからはやることが定まってきています。
まずは画面UIで見えているテキスト情報をもとにクリックできるか試す
ダメだった場合、HTML解析しタグ情報を正確に取得し、コードに反映させる。
このセクションでは右上の「新規作成」→「新規放送作成」のスキームは1でクリアできました!
必要情報の入力
1のそのままテキスト情報から同定する作戦はうまくいかなかったので、2のHTML解析を試してみます。
判明したこと:
タイトル: placeholder="放送タイトルを入力" を持つinputタグ。
放送概要: placeholder="放送内容の紹介、..." を持つtextareaタグ。
ハッシュタグ: placeholder="ハッシュタグを入力" を持つinputタグ。
予約ボタン: 「日時を指定して予約」というテキストを持つbuttonタグ。
予約日入力欄: placeholder="YYYY/MM/DD" を持つinputタグ(これはHTMLから推測しました)。
予約時間(時): formcontrolname="hours" という属性を持つselectタグ。
予約時間(分): formcontrolname="minutes" という属性を持つselectタグ。予約投稿の準備
右側に日時を指定する欄が出てくるのですが、これが地味に撮ってこれなかったです。
HTML解析しそのタグを持つコンポーネントに入力をするようにする。
日付:
<input _ngcontent-ng-c92763773="" type="text" placeholder="年月日を入力" bsdatepicker="bsDatepicker" class="app-date-input__setting-date__wrapper__input ng-untouched ng-pristine ng-valid">
時間指定:<input type="text" maxlength="2" class="form-control text-center bs-timepicker-field" placeholder="HH" aria-label="hours">
分指定:<input type="text" maxlength="2" class="form-control text-center bs-timepicker-field" placeholder="MM" aria-label="minutes">
画面操作時に操作対象のところにスクロールしたり移動するアクションを追加
上のスクショは同じ状態のスクショですが、右側が出ていません。この2番のアクションを追加することで見えるようになりました。
そうすることで以下のように予約直前の状態に持っていくことができました!
予約投稿ポップアップ
指定の日時で予約をクリックさせると、以下のようなポップアップが出てきて、OKを押したら予約が完全に完了します。
手動でやると楽々とこれをクリックしていけば良かったのですが、ブラウザ制御システムを介すとこれが一瞬出てきてはすぐに消えてしまうという謎の現象に苛まれてしまいました。
それによってOKがクリックできない!!
Cursorには10往復くらいやりとりして色々と改変していきましたが、効果が出ずにいました。
Anti-botの強化
人の操作の模倣など
完全に行き詰まってしまったので、ChatGPTに聞いてそれをCursorに提案してみたら案外うまくいきました!
どうやら上のはポップアップというよりも “confirm ダイアログ“という仕組みのようで、それをキャッチするように作り直したら良いよと教えてくれました。
そうしたらビンゴ!でうまくそれをキャッチしてくれて無事に予約ができるようになりました。以下スクショの通り「テスト投稿」が追加されています。(すぐに予約は取り消したためステータスが「作成中」となっています)
気づき
Replitである程度は爆速でアプリ開発していきますが、今回のWebブラウザ操作のように苦手分野もあるようです。そこで何回もやっても課金が嵩んでしまうだけで、徒労で終わるケースが多いように思います。
こういったときの場合はCursorでじっくりとコードと挙動を見ながらやっていく方が近道だと身に染みてわかりました。
また、VibeCodingでは行き詰まるシーンが多々ありますが、その時は別の種類の生成AIにも相談してみると案外良いこともあります。お医者さんのセカンドオピニオン的な感じですね!
Day15のタスク
これで全てのキーとなる機能が一応はできました。本日は以下をできるところまでやってみます。
Replitに組み込み、2時間くらいの音声データでVoicy投稿テスト
SpotifyのRSSフィードではなく、ブラウザ操作でできるかトライ
ここまで少し整理
細かなバグ修正





