先着が始まった瞬間、サイトが順番待ちのページになる:8,000 バイトの関門を、15KB の案内ページがすり抜けた
トレカダッシュ 開発の記録 / 2026年9月
iOS アプリ「トレカダッシュ」は、通販サイトの販売ページを定期的に読んで、先着や抽選の情報を集めています。前に書いたとおり、「取れた」の判定に穴があり、案内ページを成功と読んでいた事件がありました。その判定を直したのと同じ日(2026 年 9 月 7 日)のうちに、同じ種類の穴が、別の形でもう 1 つ見つかりました。
しかも、それは、いちばん取りこぼしてはいけない瞬間に起きていました。
数字は、2026 年 9 月 7 日の作業の記録から書いています。
先着が始まった瞬間に、サイトが順番待ちのページになる
報告が来ました。「イオンスタイルオンラインにも、先着があるみたいだよ」「14 時ちょうどに、販売が始まったみたい」。そこで、その時刻に、実際に取得を試しました。
| 取得の方法 | 結果 |
|---|---|
| 素のリクエスト | 403(ボット対策で拒否) |
| 取得サービスの安い設定 | 200、15,188 バイト、題名「アクセス集中によるお知らせ」 |
| 取得サービスの super | 200、15,188 バイト、同じ |
| 取得サービスの super + render | 200、15,459 バイト、同じ |
先着が始まった瞬間、サイト全体が、順番待ちのページになります。どの設定で取っても、返ってくるのは、同じ案内ページです。
8,000 バイトの関門を、15KB の案内ページがすり抜けた
この日の先に入れた「取れていない」の判定は、8,000 バイト未満の短いページの中の、JavaScript を求める案内を見るものでした。大きなページには、まっとうなページにも、同じ一文が常に入っているからです。
ところが、この順番待ちのページは約 15KB あります。関門をすり抜けて、「取得は成功。商品は 0 件」と読まれていました。いちばん取りこぼしてはいけない瞬間に、静かに取りこぼす状態です。
直し方は、ページの大きさではなく、題名(title)を見ることでした。題名に「アクセス集中」や「順番にご案内」が出ているときは、失敗として扱います。本文の一部に、その言葉が出ているだけの、まっとうなページを巻き込まないよう、見る場所を題名に限りました。
あわせて、頻度を 3 時間おきから 15 分おきにしました。1 回約 21 クレジットと高めですが、1 日に約 6,000 クレジットで、残量の 92% に収まります。
同じ日に見つけた、もう 2 つの「遅さ」
先着の速さを測っていて、別の原因も見つかりました。
Amazon の 13 分は、「取得」ではなく、「AI の審査」だった。Amazon の監視は 30 分おきで、1 回のスキャンに 13 分かかり、最悪で約 43 分の遅れがありました。計器で見ると、時間の使い道は、新しい出品の AI による審査(1 日 421 回、約 10 円)でした。取得そのものは、1 日 1,047 クレジットで安い。原因は、15 のジャンルを、1 つずつ直列に処理していたことでした。ジャンルどうしは独立なので、4 本を並列にして、間隔を 10 分、1 回を 8 分にしました。AI の審査は、新しい出品だけに走るので、巡回の回数が増えても、費用は増えません。
速く見つけても、17% は通知していなかった。見つけることが速くなっても、その先の通知が止まっていれば、意味がありません。通知が届いた数を数えたら、まだ穴がありました(通知の数を数えた話は、別の記事に書いています)。
分かったこと
判定の穴は、いちばん大事な瞬間に、いちばん広がる。
- 案内ページの形は、1 つではない。短い案内も、大きな順番待ちのページもあります。大きさでは、見分けられません。
- 見る場所を変えると、巻き込みが減る。本文ではなく題名にしたので、まっとうなページを巻き込みません。
- 報告を受けたら、その時刻に、その場で測る。「14 時に始まった」は、再現できる最後のチャンスでした。
- 遅い理由は、実際の時間の使い道で確かめる。Amazon の 13 分は、取得ではなく、直列の AI 審査でした。
この話に出てくるもの
- トレカダッシュ — トレカの抽選・予約・先着の情報を集める iPhone アプリ
- 「取れた」と読んでいたのは、ただの案内ページだった — 同じ日の先に直した、同じ種類の穴
- 同時実行の枠を増やす前に見るもの — 同じ日の、枠の話
- 「1 分おき」の監視は、1 件あたり 10 分に 1 回だった — 見直しの間隔と、通知の数
ほかの記録
- 同時実行の枠を増やす前に見るもの:2 コアのサーバーで、枠を 8 から 14 にした判断と、半分間違っていた前の結論 — 先着の監視を速くしようと間隔を詰めると、1 分おきの瞬殺監視が枠の順番待ちで遅くなった。枠を 8、11、14 と変えて測った。上限の正体は CPU ではなく、楽天 API の 1.5 秒待ちで枠を握る処理だった。
- 競合サイトと突き合わせて、取りこぼしを数えた:最初の「カバー率 23%」は測り方の間違いで、本当は 49% だった — 他のサイトが出している抽選を、こちらが出せているかを数えた。最初の 23% は、商品名の書き方の違いと期限切れの記事で歪んでいた。直して 49%、穴埋めの 5 つの問題を直して 90% に。規約で自動取得が禁止のサイトは取り込まなかった。
- 自分で作った仕組みが、自分を傷つけた 4 つの記録:要約が条件を捨て、1 つの未定義が保存を止め、点検が本番の IP を閉め出された — 「15 文字程度」の指示で応募の条件が 671 件の点検で抜けていた、undefined が 1 つで保存が全部失敗し 1 日の消費の 41% を溶かした、点検の 6 並列で本番と同じ IP が拒否された、直っても鳴り続ける警告を作った。
コメント
感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。
押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。