Python でwebサイトをスクレイピングしていて、タグの style
属性にインラインで書かれているCSSの解析が必要になった際のメモ。
ライブラリの選定
Beautiful Soup ではCSSを扱うことができないようなので、要件を満たすライブラリを探す。
PyPIで検索して、上位に出てきた cssutils を使ってみることにした。 ドキュメント がきちんと書かれていて、開発も続いているようなので良さそうな感じ。
今回は Python 3.3.3 の環境で試してみた。インストールは pip
で一発。
$ python -V
Python 3.3.3
$ pip install cssutils
CSSのパース
今回はインラインのCSSを解析するので cssutils.parseStyle
を使用する。パース用のインターフェースは色々と用意されていて、今回は試していないがファイル名やURLを指定してパースすることもできるようだ。また、オプショナルな引数で文字コードを指定することもできる。
>>> from cssutils import parseStyle
>>> style = parseStyle('width: 300px; margin: 0 20px 0 10px;')
>>> type(style)
<class 'cssutils.css.cssstyledeclaration.CSSStyleDeclaration'>
インラインのCSSをパースすると、 cssutils.css.CSSStyleDeclaration
クラスのオブジェクトが得られる。ここから width
や margin
プロパティで指定されている値を取得することが今回やりたいことだ。
プロパティと値の取得
プロパティの値を文字列で取得するだけなら簡単である。
>>> style.width
'300px'
>>> style.margin
'0 20px 0 10px'
値が複数の要素で構成されている場合や単位を考慮したい場合など、もう少し詳細に解析したいときは cssutils.css.Property
クラスと cssutils.css.PropertyValue
クラスのオブジェクトを使用する。
>>> p = style.getProperty('margin')
>>> type(p)
<class 'cssutils.css.property.Property'>
>>> v = p.propertyValue
>>> type(v)
<class 'cssutils.css.value.PropertyValue'>
cssutils.css.PropertyValue
クラスは複数の要素で構成されている値を個別に扱うことができる。
>>> v.length
4
>>> v[0]
cssutils.css.DimensionValue('0')
>>> v[1]
cssutils.css.DimensionValue('20px')
値の各要素はリスト風の操作で取得することができる。今回は cssutils.css.DimensionValue
クラスのオブジェクトが返ってきた。このクラスは px
や em
などの単位を扱うことができる。
>>> v[1].value
20
>>> v[1].dimension
'px'
>>> v[1].cssText
'20px'
他にも cssutils.css.ColorValue
や cssutils.css.URIValue
などといったクラスが用意されており、値の形式によって適切なオブジェクトが生成されるようだ。
まとめ
- cssutils を使うことで、PythonでCSSをパースすることができる。
- 複数の要素からなる値や単位付きの値を簡単に扱うことができる。