Xpathとは
XML形式の文書のなかの特定の要素を一意に指定するための構文である。スクレイピングでは主にhtmlのスクリプトに対して使われる。
Xpathの記法
基本
htmlは入れ子構造の構文が用いられる。階層構造を辿るように書く点はディレクトリの絶対パスと同様、例えば
サンプルコード(長いので折りたたみます)
<!DOCTYPE html>
<html lang="ja">
<head>
<style>
.theme{
color : green;
}
.subtitle{
color : violet;
}
.chemical{
color : skyblue;
}
</style>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>植物</title>
</head>
<body>
<p class="theme">
<b>植物</b>
</p>
<p>肥料</p>
<h1 class="subtitle">肥料の三要素</h1>
<h2 class="chemical">窒素</h2>
<ul id="窒素">
<li>光合成の促進</li>
<li>葉や茎の成長</li>
</ul>
<h2 class="chemical">リン酸</h2>
<ul id="リン酸">
<li number="1">開花</li>
<li number="2">結実</li>
</ul>
<h2 class="chemical">カリウム</h2>
<ul id="カリウム">
<li number="1">根の成長</li>
<li number="2">植物の免疫力</li>
</ul>
<h3>微量元素</h3>
<ol>
<li number="1">鉄</li>
<li number="2">マンガン</li>
<li number="3">ホウ素</li>
<li number="4">亜鉛</li>
</ol>
</body>
</html>
↑このページで「<h3>微量元素</h3>」という要素を指定したいときは
/html/body/h3
<h3>微量元素</h3>
とすれば良い。
途中までを省略して "//h3" とすることもできる。
ちなみに上のコードで下のようなページが作れます。内容は100%自分の趣味です
テキストのみ抽出
「微量元素」という文字列のみを抽出したい場合は text() をつけて
/html/body/h3/text()
微量元素
兄弟要素を属性で指定
上の例では「鉄」「マンガン」「ホウ素」「亜鉛」は全て/html/body/ol/liであり、number属性を用いなければ区別できない。そこで
要素[@属性 = 属性値]
という構文を用いる。
/html/body/ol/li[@number = "2"]/text()
マンガン
指定した属性値を持つもの以外をまとめて指定
[]の中身をnot()で囲うことで否定形となる。
/html/body/ol/li[not(@number = "2")]/text()
鉄
ホウ素
亜鉛
number属性が1,3,4のものが抽出されている。
リスト内の要素に属性が当てられていない場合
上の例では/html/body/ul[@id="窒素"]/liに"<li>光合成の促進</li>"と"<li>葉や茎の成長</li>"があるが、この2つは属性で区別できない。このような場合は
/html/body/ul[@id="窒素"]/li[1]
<li>光合成の促進</li>
のようにインデックスで取得できる。
複数選択したい場合は
//li[1 or 2]
とは書かず、
//li[position()=1 or position()=2]
とする
- position()=last 最後の要素を取得
- position()>3 4番目以降の要素を取得
なども可能
知っておくと便利なもの
属性値が指定した文字列と前方一致
要素[starts-with(@属性,"指定した文字列")]
ends-withで後方一致になる。(xpath2.0から実装)
属性値に指定した文字列を持つ要素を抽出
要素[contains(@属性,指定した文字列)]
"@属性"を"text()"に変え、[contains(text(),"文字列")]でテキスト内に指定した文字列を持つ要素を抽出できる。この場合、@(アットマーク)は使わない。
論理積的な記述
要素[条件1 and 条件2]
li[contains(@class,hogehoge1) and not(contains(@class,hogehoge2))]
andではなくorを使うと論理和的な記述になる。
省略しない記法
p/a
は、
p/child::a
の省略形である。どちらも「pの子要素のa」という意味は変わらないが、「子要素の」の部分が上の例では省略されているが下の例では「child」と明示されている。このような前後のノードの関係性を示すものを軸という。
/軸::ノード
であり、childは軸のデフォルトとして設定されているため、軸に何も指定しないと上の例のように子要素を辿る。
便利なサイト
-
Xpath Playground
テキストをコピペしてxpathを欄内に入力すると指定された要素が出力される。xpathのデバッグに使えて便利