Webサイト上からデータを自動的に取得するには2つの方法があります。1つはPythonなどのプログラミング言語でWebクローラーを作る、もう1つはOctoparseのようなWebスクレイピングツールでデータを取得するのです。しかし、どれにしても、XPathは重要な役割を果たしています。XPathの書き方が分かれば、データをより正しくて効率的に取得できます。
それで今回の記事ではXPathの基本概念からXPathの書き方、よく使う関数まで詳しく紹介したいと思います。
Xpathの基本概念
この部分では、XPathの基本概念を簡単に紹介します。
1. XPathとは?
XPath (XML Path Language)とは、ツリー構造となっているXML/HTMLドキュメントからの要素や属性値などを指定するための簡潔な構文(言語)です。
Webページは通常HTMLで記述されるから、XPathはWebページの情報を取得する時によく利用します。ブラウザ(Chrome、Firefoxなど)でWebページのHTMLを表示するする場合、F12キーを押すことで、対応するHTMLドキュメントに簡単にアクセスできます。

2. XPathの仕組み
XPathは具体的にはどのように動作するのかを見てみましょう。下記の画像はHTMLドキュメントの一部です。

HTMLは、ツリー構造のように、異なるレベルのがあります。この例では、レベル1はbookstoreで、レベル2は bookです。Title、author、year、priceはすべてレベル3です。
山括弧(<bookstore>など)を含むテキストはタグと呼ばれます。HTMLの要素は通常、開始タグと終了タグで構成され、その間にコンテンツが挿入されます。以下の形になります。
<○○>(開始タグ)ここにコンテンツが入ります… </○○>(終了タグ)
XPathはスラッシュ “/” で区切りながら階層を記述し、基準となるノードから別のノードを指定できます。URLと似ています。この例では、要素「author」を検索する場合、XPathは次のようになります。
/bookstore/book/author
それがどのように機能するかをよりよく理解するには、コンピューター上の特定のファイルを見つける方法を参照してください。

「author」という名前のファイルを見つけるには、正しいファイルパスは\ bookstore \ book \ authorです。
コンピューター上のすべてのファイルには独自のパスがあるように、Webページ上の要素もパスがあります。そのパスはXPathで記述されています。
ルート要素(ドキュメントの一番上の要素)から始まり、中にあるすべての要素を経由して目標要素に至るXPathは、絶対XPathと呼ばれます。
例: /html/body/div/div/div/div/div/div/div/div/div/span/span/span… |
絶対XPathは長くて混乱する可能性があるため、絶対XPathを単純化するために、「//」を使用して途中までのパスを省略することができます(短いXPathとも呼ばれる)。
たとえば、
絶対XPath: /bookstore/book/author 短いXPath: //author |
3. XPathを表示・書くには
【Google Chromeの場合】
Chromeでこのページを表示し、右クリックメニューの[検証]から開発者ツールを表示します。Elementタブのhtmlで、要素を右クリックします。メニューの[Copy] → [Copy XPath ] でその要素を取得するためのXPathがクリップボードにコピーされます。

表示されているElementタブのhtmlから “Ctrl + F” で検索欄を表示します。XPathを入力すると、得られる要素が選択されるはずです。

また、「XPath Helper」という拡張機能を追加することもできます。XPathを入力すると、一致する結果が表示されます。(XPath Helperをインストールする)

【Firefoxの場合】
Firefoxの旧バージョンに搭載されている拡張機能「Firebug」が利用できます。
FirefoxでWebページを開く➡Firebugボタンをクリック➡ページ内の要素をクリック➡その要素のXPathが表示されます。

XPathの書き方
この部分はXPathによるWebページ(HTML)からデータを指定・取得する方法、つまりXPathの書き方を紹介します。
1.タグ(要素)で指定する
下記のHTMLサンプルで、文章が<html> </html> のように、<></>といった記号で囲まれているのが分かります。このような<></>といった記号を、タグと言います。
<タグ名>ここにコンテンツが入ります… </タグ名>
最初のタグを「開始タグ」、終わりのタグを「終了タグ」といいます。そしてこの開始タグから終了タグまでの全体を、要素と呼びます。
下記のHTMLの中で赤色で表示された部分はタグです。(Firefoxで青色、Chromeでは紫色で表示されます。)

下記はHTMLでよく見かけるタグのまとめです。詳しくのはこの記事を合わせてご覧ください!
タグ | 説明 |
<a> </a> | リンクを設定する |
<p> </p> | 段落を表す |
<div> </div> | 特定の範囲をグループ化する |
<li> </li> | リストの項目を表す |
<img> </img> | 画像を表示する |
<table> </table> | 表を作る |
<tr> </tr> | 表の行を表す |
<td> </td> | 表の列を表す |
XPathの最も一般的な書き方は、スラッシュ “/” で区切りながらタグを記述します。
例えば、このHTMLから『Harry Potter』を取得したい場合は、ツリー構造の上から順に『htmlタグ→bodyタグ→h1タグ』と指定できます。次のように書きます。
/html/body/h1
また、『//』を用いて、途中までのパスを省略することができます。
//h1

タグを複数に合致する場合に、N番目のタグを指定することができます。この例では、『7,631円』を取得する場合、「div」の行から2行目の「span」であるため、次のように書きます。
//div/span[2] |
抽象化にすると、タグ(要素)で書くXPath構文はこうなります。
//タグ名 //タグ名/タグ名 |
2.属性で指定する
属性とはタグの中に記載されていて、タグの情報を細かく表すものです。タグに属性をつけることで、要素の効果を指定したり、具体的な指示を付け加えることが出来ます。属性は通常、「id=”booksTitle”」のように表示されます。なお、属性は複数指定する事も可能です。
<タグ名 属性名=”属性値”>最も |
最も一般的な属性には、href、title、style、src、id、classなどがあります。
XPathでは属性を『@』関数で表します。
例えば、『Harry Potter』を取得したい場合、XPathは次のように書きます。
//h1[@id=”booksTitle”]

抽象化にすると、属性で書くXPath構文はこうなります。
//タグ名[@属性名=”属性値”] |
もし同じ属性を持つすべての要素を取得する場合、次のように書きます。
//*[@属性名=”属性値”] |
3.テキストで指定する
下記のようにタグで囲まれているのはテキストです。
<タグ名>ここにテキストが入ります… </タグ名> |
Webページからデータを取得するのは、通常ページ内のコンテンツまたはテキストを取得することです。ですから、取得したいテキストを直接指定することができます。
XPathではテキストを『text()』の関数で表します。
例えば、『Harry Potter』を取得したい場合、テキストで指定すると、次のように書きます。
//h1[text()="Harry Potter"]

抽象化にすると、属性で書くXPath構文はこうなります。
//タグ名[text()=”取得するテキスト”] |
もし同じテキストを持つすべての要素を取得する場合、次のように書きます。
//*[text()=”取得するテキスト”] |
4.タグ関係で指定する
HTMLのツリー構造において、すべての要素が親子/兄弟関係を持っています。
1つまたは複数の要素を含む要素は親要素と呼ばれ、含まれる要素は子要素です。子要素は1つのみの親があり、親の開始タグと終了タグの間にあります。同じ親を持つ要素は兄弟要素と呼ばれます。
具体的な例も見てみましょう。
以下のサンプルは、<body>要素を基点に、<body>要素は<h1>要素と<div>要素の親で、<h1>要素と<div>要素は、<body>要素の子です。親子/兄弟関係にある要素を取得し、それぞれにスタイルを変更する例です。
<h1>要素と<div>要素は、同じ親<body>要素を持つため、兄弟要素です。
また、<div>要素は2つの<span>要素の親ですから、2つの<span>要素は<body>要素の子孫要素です。

カレント要素を基点として、親子、もしくは兄弟関係にある要素を取得することができます。例えば、『7,631円』を取得したい場合、タグの関係で指定すると、下記のように書くことができます。
<div>要素の子要素とする場合
//div/span[2] |
<body>要素の子孫要素とする場合
//body//span[2] |
<span class=”author notFaded”>要素の兄弟要素とする場合
//span[@class=”author notFaded”]/following-sibling::span[1] |
<span class=”tax_postage”>要素の兄弟要素とする場合
//span[@class=”tax_postage”]/preceding-sibling::span[1] |
兄弟関係のあるタグを指定するには『following-sibling::』と『preceding-sibling::』という2つの関数をよく使います。
- 『following-sibling::』は、指定された要素より後の兄弟要素を指定する
- 『preceding-sibling::』は、指定された要素より前の兄弟要素を指定する
『following-sibling::』は、テーブル要素を指定する時に大活躍します。例えば、下記のHTMLサンプルがあります。

このHTMLはページに変更すると、以下のようなテーブルの形になります。
店名 | 12345 |
ジャンル | 居酒屋 |
予約可否 | 予約可 |
この例では、店名の『12345』取得します。ただし、<td>要素が複数あり、//td[1]で対応できなくなります。また、もし複数のページから、同じ構造のテーブルを一括取得する場合、固定的な値「店名」を基点として、『following-sibling::』を使うほうが薦めです。次のように書きます。
//th[text()=”店名”]/following-sibling::td[1] |

抽象化にすると、タグ関係で書くXPath構文はこうなります。
親要素 | //基点要素のタグ名/.. |
子要素 | //基点要素のタグ名/子要素のタグ名 |
子孫要素 | //基点要素のタグ名//子孫要素のタグ名 |
より後の兄弟要素 | //基点要素のタグ名/following-sibling::より後の兄弟要素のタグ名 |
より前の兄弟要素 | //基点要素のタグ名/preceding-sibling::より前の兄弟要素のタグ名 |
もし上記の構文で複数に合致する場合に、[N]を付けてN番目のタグを指定することができます。
XPathによく使う関数
この部分では、より正しくデータを指定するには、XPathによく使う関数を紹介します。
1. contains() :特定の文字列が含まれる要素を指定する
contains() は通常、属性値またはテキストに含まれる文字列ををあいまい検索することに使われます。
contains(@class,”XXX”) :属性値に特定の文字列が含まれている要素を指定する

例えば、このHTMLからclass属性にRedがつくものをすべて取得したい場合、次のように書きます。
//span[contains(@class,“Red”)] |
つまり、このXPathは、classにRedを含むspan要素を取得するという意味になります。

contains(text(),”XXX”) :テキストに特定の文字列が含まれる要素を指定する

例えば、このHTMLから『Rowling』という文字を含んでいる要素を指定したい場合は、次のように書きます。
//span[contains(text(),”Rowling”)] |
2. position():特定位置の要素を指定する
前回の記事では、[] (スクウェアブラケット)で数値を囲むと、順番の要素を取得できることを紹介しました。positionでもN番目の要素を指定することもできます。以下のサンプルHTMLを例で説明します。

position()=
例えば、上記のHTMLで『商品3』は4番目のth要素であるため、次のように書きます。
//tbody/th[4] |
position()=を使うと、次のように書きます。
//tbody/th[position()=4] |
position() >
『広告』以外の要素を取得する場合、『広告』は1番目のth要素であるため、次のように書きます。
//tbody/th[position()>1] |

3. and/not/or:複数の条件が含まれている要素を指定する
複数の条件が同時に含まれている要素を指定したい場合はand/not/or関数を使います。
and ー 複数の条件に一致する要素を指定する

このHTMLから、『S_20』と『pdf』を含むhrefを取得したい場合は、次のように書きます。
//a[contains(@href,“S_20”) and contains(@href,“pdf”)] |
not ー 特定条件を含まない要素を指定する

このHTMLからhttps://helpcenter.octoparse.jp/hc/ja/xpath/S_10.html以外の@hrefを取得したい場合は、次のように書きます。
//a[not(contains(@href, “S_10”))] |
or ー いずれかの条件に一致する要素を指定する

このHTMLから、MかLを含むhrefを取得したい場合は、次のように書きます。
//a[contains(@href,”M_”) or contains(@href,”L_”)] |
また、MかL以外のhrefを取得したい場合は、notとorを組み合わせると、次のように書きます。
//a[not(contains(@href,”M_”) or contains(@href,”L_”))] |
もしXPathの構文・関数をもっと詳しく習いたいならば、この記事をご覧ください。
まとめ
以上はXPathの紹介でした。いかがでしょうか?Xpathはスクレイピングで簡単に使いこなせるようになるので、とてもオススメです。正規表現を組み合わせれば、よりきれいでデータを取得することができるので、クローラーなどを作りたい人は是非勉強してみてください!
