スクレイピングで要素を取得する — セレクタはもうAIに書かせていい
スクレイピングで一番時間を取られるのは、コードを書くところではありません。 「この値はどのセレクタで取れるのか」を調べるところです。 DevTools を開いて、要素を選んで、クラス名を見て、試して、ずれていてまた直す。
ここは2026年のいま、ほぼ丸ごと AI に渡せます。 XPath の軸や述語を暗記する必要も、もうありません。 ただし投げ方を間違えると、一見それっぽいのに次の日には壊れているセレクタが返ってきます。
先に結論
- セレクタは AI に書かせる。 文法を覚えるより、出てきたものを検証できるほうが実務では効く
- 渡すのはページ全体ではなく、該当要素の周辺だけ。 DevTools の
$0.outerHTMLで切り出す - 検証はブラウザのコンソールで件数を見る。
document.querySelectorAll(セレクタ).lengthが期待どおりかだけ見れば足りる - DevTools の「完全な XPath をコピー」は使わない。 構造に依存しすぎて、すぐ壊れる
やることは「セレクタを1本決める」だけ
ライブラリが何であれ、やることは変わりません。 HTML を取ってきて、欲しい要素を指す文字列を1本決めて、そこからテキストや属性を取り出す。それだけです。
CSSセレクタとXPath
要素の指し方は2系統あります。どちらでも同じことができるので、好きなほうで構いません。
| CSSセレクタ | XPath | |
|---|---|---|
| クラスで指す | .price | //*[@class="price"] |
| 属性で指す | [data-id="42"] | //*[@data-id="42"] |
| 子孫をたどる | .item h3 | //*[@class="item"]//h3 |
| n番目 | li:nth-child(2) | //li[2] |
| テキストで探す | できない | //a[contains(text(),"詳細")] |
| 親をたどる | できない(:has() で近いことは可能) | //span[@class="x"]/parent::div |
実務では CSSセレクタで足りることがほとんどです。 「このテキストを含むリンク」「この要素の親」を取りたいときだけ XPath に切り替える、くらいの温度でいいと思います。
DevToolsで調べる
従来のやり方です。手順自体は今でも変わりません。
- F12 で DevTools を開く
Elements(要素)タブを表示します - 左上の矢印アイコンをクリック
ページ上の要素をクリックすると、対応する HTML が反転します - 欲しい値の要素を選ぶ
クラス名やdata-属性を確認します - 右クリック → Copy → Copy selector
CSSセレクタがクリップボードに入ります
「完全なXPathをコピー」が壊れる理由
DevTools には「Copy full XPath(完全な XPath をコピー)」もありますが、 スクレイピングでは使わないでください。
これが出力されるものです。
構造に依存しきっている
/html/body/div[2]/div/div[3]/main/section[2]/ul/li[4]/div/h3/a
上から何番目か、だけで場所を指しています。
サイト側が div をひとつ増やしただけで、全部ずれて何も取れなくなります。
広告の有無や、ログイン状態でも変わります。
欲しいのはこちらです。
意味で指している
.product-list .product-card h3 a
セレクタの良し悪しは「短さ」ではなく「構造が変わっても生き残るか」です。 優先順位はこうなります。
| 優先度 | 手がかり | 例 |
|---|---|---|
| 高 | id / data- 属性 | #main、[data-testid="price"] |
| 中 | 意味のあるクラス名 | .product-card、.price |
| 低 | タグ構造・nth-child | div > div > li:nth-child(3) |
| 最低 | ビルドツールが生成したクラス | .css-1q2w3e4、.sc-bdVaJa |
最後のものは、サイトをビルドし直すたびに変わります。見かけたら避けてください。
AIに書かせる
ここまでの判断を、まとめて AI にやらせます。 人間がやるべきなのは何を渡すかと出てきたものを検証することの2つだけです。
渡すのはページ全体ではない
ページの HTML を丸ごと貼るのは悪手です。 ヘッダー・ナビ・広告・スクリプトで埋まって、肝心の部分が薄まります。長いページだと入りきりません。
DevTools で該当要素を選んでから、コンソールで切り出します。
DevToolsのコンソールで実行
// $0 は Elements タブで選択中の要素
copy($0.outerHTML); // クリップボードにコピーされる
// 一覧ものなら、親を選んで1件だけ渡せば十分
copy($0.children[0].outerHTML);
一覧ページから複数件取りたい場合も、渡すのは1件分の HTML で足ります。 繰り返しの構造は1件見れば分かるので、AI は残りを推測できます。 かえって精度が上がり、トークンも節約できます。
プロンプト
そのまま使える形
次の HTML から、以下の値を取得する CSSセレクタを出してください。
欲しい値:
- 商品名
- 価格
- 詳細ページへのリンク(href)
条件:
- id か data- 属性があればそれを最優先で使う
- 次点で意味のあるクラス名を使う
- nth-child や、上から何番目かに依存する指定は使わない
- ビルドツールが生成したと思われるクラス名
(.css-xxxx、.sc-xxxx のようなもの) は使わない
- 一覧の繰り返し部分は、1件を指すセレクタと
全件を指すセレクタの両方を出す
- HTML から判断できなかった項目は推測で埋めず、
「判断できなかった項目」として最後に挙げる
--- HTML ---
($0.outerHTML を貼る)
効くのは「使ってはいけない指定」を先に列挙しているところです。
何も言わないと、AI は確実に当たる nth-child だらけのセレクタを返してきます。
その場では動くので、検証も通ってしまいます。壊れるのは1週間後です。
コンソールで件数を見る
出てきたセレクタは、コードに入れる前にブラウザで確かめます。 対象ページを開いて、コンソールに貼るだけです。
対象ページのコンソールで
// 件数が期待どおりか
document.querySelectorAll('.product-card').length; // 20
// 中身が正しいか(最初の3件だけ見る)
[...document.querySelectorAll('.product-card .price')]
.slice(0, 3)
.map(el => el.textContent.trim());
// ["¥1,980", "¥2,480", "¥3,200"]
見るのは3点です。
| 確認 | ずれていたときの意味 |
|---|---|
| 件数が合うか | 0 件ならセレクタが外れている。多すぎるなら絞りが足りない |
| 中身が欲しい値か | 隣の要素を拾っている。親をひとつ挟むか、属性で絞る |
| 別のページでも同じ件数か | そのページだけに合わせたセレクタになっている |
3つ目が大事です。1ページで動いたセレクタが、他のページで動くとは限りません。 商品が1件しかないページ、売り切れ表示があるページ、といった例外で崩れます。 最低でも2〜3ページで試してください。
壊れたときも同じやり方で直す
スクレイパーは必ず壊れます。サイト側がリニューアルすれば終わりです。 そのときも手順は同じで、新しい HTML を切り出して投げ直すだけです。
このセレクタが取れなくなりました。
新しい HTML を貼るので、同じ値を取るセレクタに直してください。
前のセレクタ: .product-list .product-card .price
取れていた値: 価格("¥1,980" のような文字列)
--- 新しい HTML ---
($0.outerHTML を貼る)
「前は何で取れていたか」を一緒に渡すのがコツです。 欲しい値の説明だけだと、別の場所にある似た値を拾ってくることがあります。
取ったあとに詰まるところ
JavaScriptで描画されるページ
DevTools で見えているのに、取得すると空。これが一番多いハマり方です。
原因は、DevTools が表示しているのは 描画後 の DOM で、 HTTP で取得できるのは 描画前 の HTML だからです。 中身を JavaScript で後から差し込むページだと、この2つは別物になります。
切り分けは簡単で、ブラウザで「ページのソースを表示」(view-source:)して、
欲しい文字列が入っているかを検索するだけです。
入っていなければ JavaScript 描画です。
その場合の選択肢は2つあります。
- データの出どころの API を直接叩く……DevTools の Network タブで、その値を運んでいるリクエストを探します。JSON が返ってくるなら、HTML を解析するより速くて確実です
- ヘッドレスブラウザを使う……Playwright や Selenium で実際に描画させてから取ります。確実ですが重いので、上が無理なときに
文字コードと相対URL
- 文字化け……古いサイトは EUC-JP や Shift_JIS のことがあります。HTTP ヘッダーの
Content-Typeと、HTML のmeta charsetが食い違っていることも多いので、両方確認してください - リンクが
/item/123のまま……相対パスなので、取得元の URL と結合して絶対 URL にする必要があります
やる前に確認すること
技術とは別に、先に見ておく話です。
- 著作権
- 日本の著作権法には、情報解析のための利用について定めた30条の4があります(2019年1月施行)。 解析が目的で、著作物を「享受」する目的でない利用は、原則として許諾なく行えます。 ただし著作権者の利益を不当に害する場合は除かれます。 取ったデータをそのまま自分のサイトに並べて公開する、といった使い方は別の話になります。
- 利用規約
- 著作権とは別問題です。規約で自動取得を禁止しているサイトは普通にあります。 法律上どうかではなく、契約として縛られます。先に読んでください。
- robots.txt
- 法的な拘束力はありませんが、運営側の意思表示です。無視する理由がないなら従ってください。
- アクセス頻度
- これが実務上いちばん重要です。短時間に大量のリクエストを投げれば、相手のサーバに負荷をかけます。 1リクエストごとに1秒以上空ける、並列で叩かない、取得は営業時間外に回す。 国内でも、過度なアクセスが問題になった事例があります。
取得した HTML はローカルに保存して、開発中はそれを読み返すようにしてください。 セレクタを試すたびに本番へアクセスする必要はありません。