XPathは、データをスクレイピングする際にOctoparseを使用する際に重要な役割を果たします。XPathを書き換えることにより、欠落したページ、欠落したデータ、重複などの問題に対処することができます。XPathは最初は難しく見えるかもしれませんが、必ずしもそうではありません。この記事では、XPathについて簡単に紹介し、さらに重要なのは、正確かつ精度の高いタスクを構築するためにXPathを使用して必要なデータを取得する方法を紹介します。
1. XPathとは?
XPath(XML Path Language)は、XML/HTMLドキュメントから要素を選択するためのクエリ言語です。XPathを使用することで、ドキュメント全体から要素を正確かつ迅速に見つけることができます。
ウェブページは一般的にHTMLという言語で記述されます。ウェブページをブラウザ(Chrome、Firefoxなど)で読み込むと、F12キーを押すことで対応するHTMLドキュメントに簡単にアクセスできます。ウェブページで見えるすべての要素は、画像、テキストブロック、リンク、メニューなど、HTML内に存在します。
XPathは、HTMLドキュメント内の目的の要素を見つけるための最も一般的に使用される言語です。XPathは、HTMLドキュメント内のターゲット要素を見つけるための「パス」として理解することができます。
XPathの動作をさらに説明するために、例を見てみましょう。
画像はHTMLドキュメントの一部を示しています。
HTMLには、木構造のような異なるレベルの要素があります。この例では、レベル1はbookstoreであり、レベル2はbookです。Title、author、year、priceはすべてレベル3です。
角括弧(<bookstore>)で囲まれたテキストはタグと呼ばれます。HTML要素は通常、開始タグと終了タグから構成され、その間に内容が挿入されます。
<tagname>Content goes here...</tagname>
XPathでは、要素の場所を指定するために、異なるレベルのタグを上から下に結ぶために「/」を使用します。この例では、要素「author」を見つけたい場合、XPathは次のようになります。
/bookstore/book/author
動作が理解しづらい場合は、コンピュータ上の特定のファイルを検索する方法を考えてみてください。
ファイル「author」を見つけるためには、正確なファイルパスは\bookstore\book\author です。見覚えがありますか?
コンピュータ上のすべてのファイルにはそれぞれ固有のパスがあり、ウェブページ上の要素も同様です。XPathを使用すると、コンピュータ上のファイルを検索するように、ウェブページの要素を迅速かつ簡単に見つけることができます。
ルート要素(ドキュメントの最上位の要素)から始まり、目的の要素まで途中のすべての要素を通過するXPathは、絶対XPathと呼ばれます。
例:"/html/body/div/div/div/div/div/div/div/div/div/span/span/span…"
絶対パスは長くてわかりにくい場合があるため、簡略化された絶対XPathでは、XPathを開始する要素を参照するために"//"を使用することができます(ショートXPathとも呼ばれます)。例えば、/bookstore/book/authorの短縮形のXPathは//book/authorとして書くことができます。この短縮形のXPathは、HTML内の絶対的な位置に関係なく、要素「book」を探し、その下の階層で目的の要素「author」を見つけます。
2. Octoparseを使用する際にXPathを学ぶ理由は?
Octoparseを使用してウェブページをスクレイピングするのは、実際にはHTMLドキュメントから要素をスクレイピングすることです。XPathは、ドキュメントから目的の要素を見つけるために使用されます。ページネーションのアクションを例に取りましょう。
「次へ」のボタンを選択してページネーションのアクションを構築した後、OctoparseはXPathを生成して「次へ」のボタンを見つけることができます。これにより、どのボタンをクリックするかがわかります。
XPathは、クローラーが正しいボタンをクリックしたり、目的のデータをスクレイピングしたりするのに役立ちます。Octoparseに行ってもらいたいアクションは、基本的にはXPathに基づいています。Octoparseは自動的にXPathを生成することができますが、自動生成されたXPathは常にうまく機能しないこともあります。そのため、XPathの書き換えを学ぶ必要があるのです。
データが欠落している、無限ループが発生している、データが正しくない、重複したデータがある、次のボタンがクリックされないなどの問題に対処する際には、XPathを書き換えることでこれらの問題を簡単に修正できる可能性が高いです。
3. XPathの書き方(チートシートも含めて)
XPathを書く前に、いくつかの重要な用語について説明していきます。
以下は、例とするサンプルHTMLです。
属性/属性値
属性は要素に関する追加情報を提供し、常に要素の開始タグで指定されます。属性は通常、name="value"のような属性名/属性値のペアで表されます。一般的な属性にはhref、title、style、src、id、classなどがあります。HTML属性に関する完全情報はこちらで確認できます。
以下の例では、id="book"は<div>要素の属性であり、class="book_name"は<span>要素の属性です。
親要素/子要素/兄弟要素
HTML要素が他の要素内に含まれている場合、他の要素を包含する要素を親要素と呼び、含まれている要素を子要素と呼びます。各要素には親要素が1つだけですが、子要素は0つ、1つまたは複数存在する可能性があります。子要素は親要素の開始タグと終了タグの間に配置されます。
以下の例では、<body>要素は<h1>要素と<div>要素の親要素です。そして、<h1>要素と<div>要素は<body>要素の子要素です。
<div>要素は2つの<span>要素の親要素です。そして、<span>要素は<div>要素の子要素です。
同じ親要素を持つ要素を兄弟要素と呼びます。例えば、<h1>要素と<div>要素は同じ親要素である<body>を持つため、兄弟要素です。
<div>要素の下に配置されている2つの<span>要素も兄弟要素です。
いくつかの一般的な実用例を見てみましょう!
「次へ」ボタンを見つけるXPathを書く方法
まず、HTML内の次のページボタンを詳しく調べる必要があります。以下のサンプルHTMLでは、2つの特徴的な要素があります。まず、属性値が「Next」というtitle属性があります。そして、コンテンツには「Next」というテキストが含まれています。
この場合、HTML内の次のページボタンを対象にするために、title属性またはコンテンツテキストのいずれかを使用することができます。
title属性の属性値が"Next"である<a>要素を検出するXPathは以下の通りです:
//a[@title="Next"]
このXPathは、title属性の属性値が「Next」である<a>要素に移動することを意味します。XPathでは、属性を対象とするには@記号を利用します。
また、コンテンツテキストに「Next」が含まれる<a>要素を見つけるためのXPathは次のようになります://a[contains(text(), "Next")]
このXPathは、コンテンツにテキスト「Next」が含まれる<a>要素に移動することを意味します。
また、title属性とコンテンツテキストの両方を使用してXPathを記述することもできます。
//a[@title="Next" and contains(text(), "Next")]
このXPathは、title属性の属性値が「Next」であり、コンテンツにテキスト「Next」が含まれる<a>要素に移動することを意味します。
ループアイテムを見つけるXPathを書く方法
ウェブページ上のアイテムのリストを対象にするには、リストアイテムの間にあるパターンを探すことが重要です。同じリストのアイテムは通常、同じまたは類似の属性を共有しています。以下のサンプルHTMLでは、すべての<li>要素に類似したclass属性があることがわかります。
観察した後に、contains(@attribute)を使用してリストのすべてのアイテムを対象にできることがわかります。
//li[contains(@class,"product_item")]
このXPathは、「class」属性に「product_item」という属性値が含まれる<li>要素に移動することを意味します。
データフィールドを見つけるXPathを書く方法
データフィールドを特定する方法は、text()または属性を使用して「次へ」ボタンを見つける方法と非常に似ています。
上記のサンプルHTMLでアドレスを対象にするXPathを書きたい場合、属性値が「address」となっているitemprop属性を使用して特定の要素を対象にすることができます。
//div[@itemprop="address"]
このXPathは、「itemprop」属性の値が「address」となっている<div>要素に移動することを意味します。
別の方法もあります。実際のアドレスを含む<div>要素は常に、その兄弟要素である「Location:」というコンテンツを持つ<div>要素の下にあることに注意してください。したがって、まず「Location」のテキストを見つけ、それに続く最初の兄弟要素を選択できます。
//div[contains(text(),"Location")]/following-sibling::div[1]
このXPathは、「コンテンツに「Location」が含まれる<div>要素」に移動し、その次の兄弟要素である最初の<div>要素に移動することを意味します。
どの目的地に複数の道があるようにHTML内の要素を対象にする方法も実際には複数あります。重要なのは、HTML内の目標要素を見つけるのに役立つタグ、属性、コンテンツテキスト、兄弟要素、親要素などを利用することです。
HTML内の任意の要素を迅速に対象にするための便利なXPath表現のチートシートを以下に示します。
表現 | 例 | 意味 |
* すべての要素にマッチ | //div/* | <div>要素のすべての子要素を選択 |
@ 属性を選択 | //div[@id="book"] | 「id」属性の属性値が「book」であるすべての<div>要素を選択 |
text() 正確なテキストを持つ要素を検索 | //span[text()="Harry Potter"] | コンテンツが正確に「Harry Potter」となっているすべての<span>要素を選択 |
contains() 特定の文字列を含む要素を選択 | //span[contains(@class, "price")] | class属性の属性値に「price」が含まれるすべての<span>要素を選択 |
| //span[contains(text(),"Learning")] | コンテンツに「Learning」が含まれるすべての<span>要素を選択 |
position() 特定の位置の要素を選択 | //div/span[position()=2] //div/span[2] | <div>要素の子要素である2番目の<span>要素を選択 |
| //div/span[position()<3] | <div>要素の子要素である最初の2つの<span>要素を選択 |
last() 最後の要素を選択 | //div/span[last()] | <div>要素の子要素である最後の<span>要素を選択 |
| //div/span[last()-1] | <div>要素の子要素である最後から2番目の<span>要素を選択 |
| //div/span[position()>last()-3] | <div>要素の子要素である最後の3つの<span>要素を選択 |
not 指定された条件とは逆の要素を選択 | //span[not(contains(@class,"price"))] | class属性の属性値に「price」が含まれないすべての<span>要素を選択 |
| //span[not(contains(text(),"Learning"))] | テキストに「Learning」が含まれないすべての<span>要素を選択 |
and 複数の条件に一致する要素を選択 | //span[@class="book_name" and text()="Harry Potter"] | class属性の属性値が「book_name」であり、テキストが「Harry Potter」となっているすべての<span>要素を選択 |
or 条件のいずれかに一致する要素を選択 | //span[@class="book_name" or text()="Harry Potter"] | class属性の値が「book_name」またはテキストが「Harry Potter」となっているすべての<span>要素を選択 |
following-sibling 現在の要素の後にあるすべての兄弟要素を選択 | //span[text()="Harry Potter"]/following-sibling::span[1] | テキストが「Harry Potter」となっている<span>要素の後にある最初の<span>要素を選択 |
preceding-sibling 現在の要素の前にあるすべての兄弟要素を選択 | //span[@class="regular_price"]/preceding-sibling::span[1] | class属性の値が「regular_price」となっている<span>要素の前にある最初の<span>要素を選択 |
.. 現在の要素の親要素を選択 | //div[@id="bookstore"]/.. | id属性の属性値が「bookstore」となっている<div>要素の親要素を選択 |
| 複数のパスを選択 | //div[@id="bookstore"] | //span[@class="regular_price"] | id属性の属性値が「bookstore」となっているすべての<div>要素と、class属性の属性値が「regular_price」となっているすべての<span>要素を選択 |
*注意:属性とテキストの属性値はすべて大文字と小文字を区別します。
*XPath表現のより包括的なリストについては、こちらで参照してください。
4. 絶対XPathと相対XPath(ループの場合)
これまでに、ウェブページから要素を直接抽出する場合のXPathの書き方について説明しました。しかし、ターゲットのアイテムのリストをまず作成し、それぞれのアイテムからデータを抽出する必要がある場合もあります。例えば、このような結果ページ:(https://www.bestbuy.com/site/promo/tv-deals)
4.1 ループアイテムに対する相対XPathも特定する
この場合、要素を直接取得するために使用する絶対XPathだけでなく、リスト内の特定のループアイテムに対する相対XPathも特定する必要があります。相対XPathは、リスト内の特定のアイテムの位置をリストに対して相対的に指定します。
Octoparseでは、データフィールドのXPathを変更する際に、2つのXPathボックスが表示されます。
4.2 絶対XPathと相対XPathの違い
絶対XPathは、ウェブページから直接データを抽出する際に使用されます。
注意:Octoparseの絶対XPathは、上記とは異なります。ここでの絶対XPathは、抽出したデータがループ内のものではなく、ウェブサイト全体からのものを指します。また、簡潔な形式で表現することもできます。
例えば、複雑な"/html/body/div/div/div/div/div/div/span/span..."ではなく「//h1[@class="..."]/span[2]...」のような形式で表現します。
ヒント:データプレビューを縦向きに切り替えることで、XPathの種類や要素のXPathを簡単に確認することもできます。
相対XPathは、ループアイテムからデータを抽出する際に使用されます。具体的には、次のようなワークフローを構築する場合に利用されます:
Octoparseの相対XPathは、要素XPathに対してループアイテムXPathに相対的な追加部分です。
4.3 ループリストのXPathと相対XPathを書く方法
例えば、<li>要素のループリストを作成し、リスト内の個々の<li>要素に含まれる要素をスクレイプしたい場合、XPath //ul[@class="results"]/li を使用してリストを特定することができます。
仮に、リスト内の要素のXPathが //ul[@class="results"]/li/div/a[@class="link"] であるとします。この場合、相対XPathは /div/a[@class="link"] となります。または、"//" を使用してこの相対XPathを簡略化することもできます。具体的には //a[@class="link"] となります。相対XPathを書く際には常に"//" を使用することが推奨されます。これにより、表現がより簡潔になります。
さまざまなXPath間の関係をより見やすくするために、以下のように記述します。
ループアイテムXPath: //ul[@class="results"]/li
ループアイテム内で特定したい要素のXPath: //ul[@class="results"]/li/div/a[@class="link"]
ループアイテムに対する相対XPath: /div/a[@class="link"]
Octoparseでは、次のようにループアイテムXPathと相対XPathを入力する必要があります。
ループリストのXPathと相対XPathが組み合わさって1つのXPathとなると、それが要素のXPathとなります。
5. XPathを修正する3つの簡単な手順
ステップ 1: ブラウザを通してウェブサイトを検査する
XPathツールを備えたブラウザを使用してウェブページを開きます(HTMLを表示し、XPathクエリを検索できるツール)。
Google Chromeを使用している場合は、Path helper(Chrome拡張機能)を常にお勧めします。
ウェブページを読み込んだら、HTML内の対象要素を検査します。
ステップ 2: 位置を特定する要素を見つける
HTML要素とその周辺の要素を注意深く検査します。目立つ要素や対象要素を特定し、その位置を特定するのに役立つものは見つけませんか?たとえば、class="sku-title"やclass="sku-header"のようなclass属性があるかもしれません。
上記のチートシートを使用して、要素を排他的かつ正確に選択するXPathを作成します。XPathは対象要素のみに一致し、HTMLドキュメント全体に他の要素が一致しないようにする必要があります。XPathヘルパーを使用して、作成したXPathが正常に機能しているかテストすることができます。
ステップ 3: Octoparseで自動生成されたXPathを置き換える
詳しいステップバイステップのチュートリアル:
6. XPathトラブルシューティングチュートリアル
ほとんどの場合、自分でXPathを書く必要はありません。ただし、より正確にスクレイプするためにいくつかの修正を行う必要がある場合もあります。
ループの問題
ページネーションの問題
データフィールドの問題
7. XPathツール
OctoparseではHTMLコードを直接確認することは簡単ではないため、他のツールを使用してXPathを生成する必要があります。
Chrome/他のブラウザ
任意のブラウザを使用して要素のXPathを簡単に取得することができます。ここではChromeを例に説明します。
Chromeでウェブページを開きます。
XPathを見つけたいアイテム上で右クリックします。
「検証」を選択すると、Chrome DevToolsが表示されます。
コンソール上のハイライトされた領域で右クリックします。
「コピー」→「XPathをコピー」に移動します。
ただし、コピーされるXPathは、属性が存在しない場合や属性値が長すぎる場合には絶対XPathとなります。XPathを修正する必要がある場合もあります。
XPath Helper(こちらからダウンロードできます)
XPath Helperは、ブラウザ上の要素にカーソルを合わせるだけでXPathを検索できる素晴らしいChrome拡張機能です。また、コンソールでXPathクエリを直接編集することもできます。結果が即座に表示されるため、XPathが正しく機能しているかどうかが確認できます。
XPathに関するさらなる情報: