コンテンツにスキップ
hsblabs OSS

Scraping KDL は CSS の部分集合を受け付ける。 この部分集合は、内部 DOM でも実ブラウザでも同じように動作する。 部分集合の外にあるセレクタは、コンパイラが拒否する。 そのため、片方のランタイムでだけ実行時に差異が露見することがない。

プロファイルの全体は selectors-v0.1.md にある。

プロファイルには、どのエンジンも同じように実装している部分が入っている。

  • 全称セレクタ *div のような型セレクタ、#main のような ID セレクタ、.entry のようなクラスセレクタ
  • 属性セレクタ。存在形の [href] と、演算子 =~=|=^=$=*=
  • 結合子。子孫、子 >、隣接兄弟 +、一般兄弟 ~
  • カンマ区切りのセレクタリスト
  • 構造擬似クラス。:first-child:last-child:only-child:empty:first-of-type:last-of-type:only-of-type:nth-child(An+B):nth-last-child(An+B):nth-of-type(An+B):nth-last-of-type(An+B):not(compound-selector)
select "table.entries tbody tr:not(.header)"

次の構文は E_SELECTOR_UNSUPPORTED として拒否する。

  • 擬似要素すべて
  • :has():is():where():scope
  • Shadow DOM 用セレクタとベンダ擬似セレクタ
  • 名前空間セレクタ
  • 識別子や文字列トークン中の CSS エスケープシーケンス
  • 属性セレクタの大小文字フラグ is
  • :hover:focus:visited:checked のような UI 状態の擬似クラス

構文自体が不正なセレクタには、別の診断 E_SELECTOR_INVALID が出る。

拒否はコンパイル時に、セレクタ内の文字位置とともに起きる。

extractor.kdl:9:5: error E_SELECTOR_UNSUPPORTED: selector byte 9: unsupported pseudo-class "has" [output.title.selection]

実装が内部でより広いセレクタエンジンを使うことはあり得る。 それでも言語バージョン 2026-07-15 のもとでは、プロファイル外のセレクタを拒否しなければならない。 これにより、一方のランタイムでコンパイルできるプログラムは、他方でもコンパイルできる。

:hover のような UI 状態の擬似クラスは、実ブラウザでしか意味を持たない。 構造擬似クラスは、どのエンジンでも同じ結果を返す。

この二種類を一つのプロファイルに入れると、ブラウザモードでは正しく動き、HTTP モードでは失敗するプログラムが書けてしまう。 プロファイルはその状態を防いでいる。 受け付けられるセレクタは、両モードで同じ意味を持つ。

:has() は、ないことに最も気付きやすい機能である。 次のいずれかを使う。

  • コレクションで親要素を選び、行の中のフィールドで子要素を探す。子を持たない行では値が欠落し、その扱いは required で制御できる。
  • 子の値だけが必要なら、子要素を直接選ぶ。親要素は必要でないことが多い。
  • ブラウザモードに限り、scope="current"evaluate-js を使う。これは可搬プロファイルからの意図的な離脱であり、browser.evaluate-js ケイパビリティと JavaScript の明示的な opt-in を必要とする。

select ノードの match プロパティが要素の個数を制御する。

挙動
one(既定) ちょうど 1 個。0 個は値の欠落。2 個以上は E_SELECTOR_CARDINALITY
first ドキュメント順で最初の要素。0 個は値の欠落。

コレクションはこれとは異なる。 コレクションの select は、一致した要素すべてをドキュメント順で返す。 1 要素につき 1 行になる。

ページ上にちょうど 1 個しか存在しないはずの要素には match="one" を使う。 ページ構造が変わったときに、ランタイムがそれを知らせてくれる。 match="first" を使うのは、複数一致が正常であり、そのうち最初の要素が欲しい場合に限る。

  • 一致は DOM のツリー順に従う。
  • セレクタリストはドキュメント順で要素を返し、重複を含まない。
  • 要素名と属性名は、HTML の ASCII 大小文字非依存の規則に従う。