理系学生日記

おまえはいつまで学生気分なのか

忍者TOOLS

CSS セレクタを学ぶなどしてみた

スクレイピングしたいなーと思いまして,スパイダリングとともにスクレイピングも載ってるという噂の spidering hacks を読むなどしてみました.

Spidering hacks―ウェブ情報ラクラク取得テクニック101選

Spidering hacks―ウェブ情報ラクラク取得テクニック101選

ところが,途中まで読んで気づいたのが,この本には Web::Scraper が載っていない.
# たぶん,出版時点で Web::Scraper は開発されてなかった
これはもう,web を使いながら自分で覚えていくしかないかなーと,ぼくは Scraper をちょっと勉強することにした.


HTML 中の抜き出したい要素をどうやって指定するかについては,CSS セレクタXPath があるみたいですね.ぼくは両方とも,概要しか知らんなーと思って,まずは楽そうな CSS セレクタを見てみた! 研修の休み時間とかに必死こいて見てたよー.たぶん,CSS セレクタの最新の仕様はこれかな.working draft だけど.Selectors Level 3
Web::Scraper の使っている HTML::Selector::XPath は CSS2 に対応していて,読んだのはどうも CSS3 になってしまってたんだけど,あんまし違いはなさそうなのでムシする.


Selector ってなんなのかなって思ってたんですが,

Selectors are patterns that match against elements in a tree.

ツリー上の要素とマッチするパターンのこと,て書かれている.
HTML も XML もツリーとして考えることができるので,ここでの tree はそういうことなんだろう.

ん,ということは CSS セレクタって

body{
font-family:"arial" ,sans-serif;
}

こういうヤツか!使ってるじゃん!CSS セレクタっていうのか.

CSS2 との違い

1.3. Changes from CSS2

This section is non-normative.

The main differences between the selectors in CSS2 and those in Selectors are:

* the list of basic definitions (selector, group of selectors, simple selector, etc.) has been changed; in particular, what was referred to in CSS2 as a simple selector is now called a sequence of simple selectors, and the term "simple selector" is now used for the components of this sequence
* an optional namespace component is now allowed in type element selectors, the universal selector and attribute selectors
* a new combinator has been introduced
* new simple selectors including substring matching attribute selectors, and new pseudo-classes
* new pseudo-elements, and introduction of the "::" convention for pseudo-elements
* the grammar has been rewritten
* profiles to be added to specifications integrating Selectors and defining the set of selectors which is actually supported by each specification
* Selectors are now a CSS3 Module and an independent specification; other specifications can now refer to this document independently of CSS
* the specification now has its own test suite

CSS2 からの違いは

  • 基本用語の定義が変わった.特に CSS2 で simple selector と呼ばれてたものが今は sequence of simple selector と呼ばれるようになって,simple selector は sequence of simple selector の構成要素を指すようになった.
  • 名前空間が各種セレクタに許されるようになった
  • 新しいコンビネータが導入
  • substring match ができる simple selector とか,新しい pseudo-class も導入された

とからしいです! ぼくは CSS2 をあんまし知らないから,違いもよくわからない!!

リファレンス

リファレンスとしては 2 章を読んだらいい感じですね.
http://www.w3.org/TR/css3-selectors/#selectors

Case sensitivity

ドキュメントを構成する言語によって違うみたいですけど,HTML は case insensitive だ!

セレクタの文法

単に使う上では,あんまし読まなくてもよかったかもしれない.

http://www.w3.org/TR/css3-selectors/#selector-syntax
Selector: Combinator で区切られた 1 つ以上の sequences of simple selectors の列
Sequence of simple selectors: combinator で区切られていない simple selectors の列
Simple selector: 以下のどれか.

  • type selector
  • universal selector
  • attribute selector
  • class selector
  • ID selector
  • content selector
  • pseudo-class

Combinator: '>', '+', '~' と空白

Simple Selector

Type selector

Type selector は HTML or XML のタグ(要素)を指定するセレクタみたいですね.
namespace とか関わってくるみたいですけど,今のところスクレイピングに使いそうにないので,そのあたりは気にしないことにしました.
そうなると,Type selector というエラそうな名前の割に単なるタグの名前になって,意外と大したことはなさそうだ.

html { .. }
a { ... }
Universal Selector

どんな要素名とも一致する,ワイルドカードみたいなセレクタですね.

*.warning { hoge; }
*#myid { hoge; }

.warning { hoge; }
#myid { hoge; }

は同じになる.

Attribute Selector
<div class="hatena-body">

の 'class="hatena-body"' の部分にマッチするセレクタみたい.

  • "[att]" att という属性させ持っていればマッチする
  • "[att=val]" att という属性が val であればマッチする
  • "[att~=val]" att に指定されている値が空白で区切られたリストであって,そのうちの一つが val であればマッチする
  • "[att|=val]" att に指定されている値の部分が val である,あるいは val- で始まればマッチする

and 条件みたいなこともできるようで,

span[hello="cleveland"][goodbye="columbus"]

ということができる.

Class selector

div.value と div[class=~value] が等しいということを前提にしていて

*.pastoral { color: green; }

[class~="pastoral"]

となるような要素に一致することになる.
こっちももちろん,and 条件が指定できる.

p.pastoral.marine

このときは,class="pastoral blue aqua marine" にはマッチするけど,class="pastoral blue" には一致しない.

ID selector

HTML でいう id 属性にマッチするセレクタ

h1#chapter 

は,id として chapter が指定されている h1 要素にマッチする

Pseudo-classes

ドキュメントツリー外の情報だとか,Simple selector では表現できないものに対するマッチ能力を与えるために導入.

a:link
a.hover
html:lang

とかはよく見たりするんですが,下みたいなのもある.なんかキモい!!

tr:nth-child(2n+1) /* represents every odd row of an HTML table */

Combinator

たぶんスクレイピングやるために一番大事なのは Combinator じゃないかなー.

Descendant combinator

名前通り,ドキュメントツリー上で,ある要素の子孫である要素,というような子孫関係を指定できる.Descendant combinator の正体は空白なので,こんな書き方になる.

A B /* 先祖として A を持つ全ての子孫 B にマッチ */
h1 em
div * p /* 少なくとも div と p の間に 1 個の他の要素を含むような p にマッチ */
div p *[href]  
Child combinator

子孫ではなくて,親子関係を指定できる! 記号は '>'.

body > p /* body の子要素である p にマッチ */
Adjacent sibling combinators

直近の兄弟関係を指定する.左側に出てくる要素の方がドキュメントツリー上では左になる.記号は '+'.

math + p /* math 要素と同じレベル (階層) で,直後に現れる p 要素 */
General sibling combinators

直近でなくてもいい兄弟関係.記号は '~'

h1 ~ pre
たぶん

必要そうなのは上の知識.他に Selector's specificity とかが定義されてたんだけど,なににつかうのかが分かんない.