競合サイトと突き合わせて、取りこぼしを数えた:最初の「カバー率 23%」は測り方の間違いで、本当は 49% だった
トレカダッシュ 開発の記録 / 2026年8月
iOS アプリ「トレカダッシュ」の目標の 1 つは、抽選販売の情報をもれなく出すことです。もれがあるかどうかを確かめるには、同じ情報を出している他のサイトと突き合わせて、「あちらにあって、こちらに無いもの」を数えるのが一番です。
2026 年 8 月 29 日の未明に、これをしました。最初に出た数字は「カバー率 23%」。ところが、それは測り方の間違いでした。この記事は、数字が 23% から 49%、そして 90% になるまでに見つけた、5 つの問題の記録です。
数字は、2026 年 8 月 29 日の作業の記録から書いています。他のサイトの名前は、出しません。
まず、全部の競合を調べた
「競合が出しているのに、このアプリが出していない記事を、無くしてほしい」という依頼でした。最初に、競合になりうるサイトを全部調べました。取り込めるかどうかは、robots.txt(機械による取得のお願い)と、利用規約を全部読んで決めました。
| 見つかったもの | 数 | 扱い |
|---|---|---|
| すでに取り込んでいたサイト | 3 | そのまま |
| 今回、取り込みを追加したサイト(A サイト) | 1 | 案件の単位で、応募リンク付き |
| 規約に禁止の条項がなく、取り込めるサイト | 2 | 今回は、手作業で突き合わせ |
| 解説記事型で、店ごとの受付一覧を持たないサイト | 複数 | 差分がほぼ無いので対象外 |
| robots.txt と規約で、自動取得を禁止しているサイト | 2 | 取り込まない。応募先のリンクにも出さない |
| ドメインが消滅していたサイト | 1 | 一覧から外す |
1 つのサイトは、robots.txt の冒頭に、日本語で禁止が書かれていました。機械的に取れるからといって、取って良いわけではありません。
突き合わせの相手は、こちらより細かかった
今回追加した相手(以下、A サイト)は、「店 × 商品 × 締切 × 応募リンク」を、1 つのページに 90 件並べていました。こちらの取り込み元は記事の単位でしたが、A サイトは案件の単位で、しかも応募のリンクが、外部の応募フォームそのもの(Google フォーム、LivePocket、抽選ロトボックス、店の公式 X)でした。数えるにも、埋めるにも、条件の良い相手でした。
問題 1:商品名の書き方が違うだけで、「取りこぼし」と数えていた
最初の数字はカバー率 23% でした。理由の 1 つ目は、商品名の書き方です。
相手 30th CELEBRATION BOX
こちら 拡張パック「30th CELEBRATION」
どちらも、もう一方を含んでいないので、素朴な「含んでいるか」では、永久に一致しません。60 件が、これで「取りこぼし」と数えられていました。
ここで、「含んでいれば同じ」にしては、いけません。「30th CELEBRATION」という名前は、「30th CELEBRATION プレミアムデッキセット」にも含まれます。別の商品を出しているのに「出せている」と数える方向の間違いです。穴が見えなくなる方向に間違えます。
直し方は、弾の呼び方(拡張パック、ハイクラスパック)と、数量の言い方(BOX、n 個セット、n 種)を落としたうえで、商品カタログの ID に結び付けることでした。決める順番は、「完全一致」、「相手の名前に含まれるカタログ名のうち、最も長いもの」、「逆向きで、1 件だけのとき」です。
問題 2:期限切れの記事を、「カバー済み」と数えていた
理由の 2 つ目は、5 件でした。ある店の、7 月 29 日が締切の記事を、相手の 8 月 30 日が締切の案件と対にして、「記事はあるのに非表示」と報告していました。前の回の別の抽選です。この 2 つの直しで、正しい数字は49% でした。
問題 3:穴埋めで作った記事が、別の商品になっていた
見つかった穴は、記事を作って埋めます。ところが、その記事を作るときに、相手の商品名を、そのまま AI に渡していました。AI は、「30th CELEBRATION BOX」を、定価 27,500 円の「30th CELEBRATION FUTURISTIC BOX」に結び付けました。10 件が、別の商品の記事になりました。
数える側は、すでにカタログの商品を 1 つに絞れていました。作る側にも、こちらのカタログの名前を渡すのが正しい直し方でした。「数える判断」と「作る判断」を、1 本にします。
この修復のときに、私自身がもう 1 つ間違えました。商品の ID を、先頭 10 文字に切り詰めた値で書いてしまい、存在しない ID の記事を 10 件作りました。点検の出力を、見やすいように slice(0, 10) で切っていて、その短い値を、そのまま処理に使ったのです。すぐ直しましたが、表示のために短くした ID を、処理に使わない、が決まりごとになりました。
問題 4:応募リンクが、t.co 以外だと、必ず捨てられていた
まとめ由来の記事に、応募のリンクを付ける処理は、店ごとの URL を、リンクを展開する関数に通していました。この関数は、t.co(X の短縮 URL)しか見ません。X の投稿のリンクは、必ず短縮されるからです。X 以外の取り込み元は、応募の URL を、短縮されていない普通の形で持っています。それを通すと、必ず 0 件になり、ウェブ検索に落ちていました。
A サイトから作った 32 件のうち、17 件が、応募先ではなく、取り込み元のサイトのページを指していました。取り込み元のサイトへ利用者を飛ばすのは、禁止にしていた状態です。
直し方は、短縮されていない普通の URL は、そのまま候補にする(採用するかの検査は、従来の検査を通す)ことでした。すでにできていた記事は、作り直せないので、突き合わせのたびに応募リンクを張り替える処理を入れ、16 件を張り替えました。
問題 5:「締切が無い」で隠した記事に、戻す道がなかった
締切が分からない、まとめ由来の記事を隠す処理がありました。この処理は隠すだけで、締切があとから分かっても、永久に隠れたままでした。直っても鳴り続ける警告と、同じ形の失敗です。相手が締切を書いている案件は、締切を入れて、表示に戻すようにしました(別の理由でも隠れている記事は、戻しません)。2 件を戻しました。
このとき、締切の時刻の扱いも直しました。読み取った日付を、「日本時間ずらし」の値のまま返していて、そのまま保存すると、9 時間ずれた締切になるところでした。日本時間の 23:59 は、協定世界時の 14:59 です。本当の時刻を返すようにしました。
結果
| 件数 | |
|---|---|
| A サイトが出している、受付中の案件 | 86 |
| こちらで、表示中 | 77(カバー率 90%) |
| フィードに無い | 0 |
| 記事はあるのに、非表示 | 2 |
| 相手が商品を特定していないので、作れない | 7 |
この作業で、記事を 32 件作り、応募リンクを 16 件張り替え、締切を入れて戻したものが 2 件ありました。
残った 9 件は、全部、理由が分かっています。
- ある店のプレミアムデッキセットは、応募ページに「対象は拡張パック 1 BOX」とだけ書いてあるので、意図して除外しています。この場合は、相手が間違っている側です。
- 「スターターセット ex 3 種」の 7 件は、相手もどの 3 種か書いていません。推測で 3 件作ると、別の商品の記事を並べることになるので、作りません。
- 残りは、最近見ていないために隠れている記事 1 件です。これにも「戻す道」が要るかもしれない、と課題に残しました。
分かったこと
数える道具の間違いは、数字を悪く見せるのではなく、穴を見えなくする。
- カバー率は、測り方を疑う。最初の 23% は、実際は 49% で、直して 90% でした。
- 「含んでいれば同じ」にしない。別の商品を、「出せている」と数えます。
- 相手の記事は、正しいとは限らない。相手が間違っている場合が、残りの中に 1 件ありました。
- 「数える判断」と「作る判断」は、1 本にする。別々だと、数えた商品と、作った商品が違います。
- 表示用に短くした値を、処理に使わない。
- 隠す処理には、戻す道を、一緒に作る。
- 取り込む前に、規約を読む。取れることと、取って良いことは、別です。
この話に出てくるもの
- トレカダッシュ — トレカの抽選・予約・先着の情報を集める iPhone アプリ
- 一度だけ生まれた誤字が、店ごとに増えていった — 商品名の取り違えの、別の経路
- 1 つの記事を商品ごとに分ける処理で起きた 3 つの取り違え — 名前の取り違えの、別の実例
- 自分で作った仕組みが、自分を傷つけた 4 つの記録 — 自分の作業で起きた失敗
ほかの記録
- 自分で作った仕組みが、自分を傷つけた 4 つの記録:要約が条件を捨て、1 つの未定義が保存を止め、点検が本番の IP を閉め出された — 「15 文字程度」の指示で応募の条件が 671 件の点検で抜けていた、undefined が 1 つで保存が全部失敗し 1 日の消費の 41% を溶かした、点検の 6 並列で本番と同じ IP が拒否された、直っても鳴り続ける警告を作った。
- X 監視の漏れ 4 つ:検索に出ない投稿、持ち主が変わるアカウント、店を探せない検索、止まった後の取り戻し — 店の X 投稿を巡回する監視で、4 店の告知が検索に 751 件取っても出なかった、登録した店が個人になっていた、店の発掘が 63 店中 11 店だった、6 日止まった後 2 時間で 2,866 件中 185 件しか読めなかった。直し方と、費用の見積もり。
- 「1 分おき」の監視は、1 件あたり 10 分に 1 回だった:速くする前に、見直しの間隔と、通知が届いた数を数えた — 先着の監視は 63 件を 1 回に 4〜9 件しか見られず、1 件あたり約 10 分に 1 回。7 日間で捕まえたのは 3 回。間隔を詰めると別の監視が遅くなり、「審査しない」ことで先着の 45% に通知が飛んでいなかった。
コメント
感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。
押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。