あっかぎのページ

スクレイピングにChromeのディベロッパーツールが便利

スクレイピングにChromeのディベロッパーツールで便利な機能が合ったので紹介します。

紹介する機能は「Copy CSS path」と「Copy XPath」です。

スクレイピングするときに抽出したい部分をCSSかXPathで指定します。その時に”class”や”id”がふっていれば簡単ですが、場合によってはDOM要素をたどって指定する必要があるときがあります。

例えば次のhtmlの場合

<div>
  <ul>
   <li>鈴木</li>
   <li>佐藤</li>
   <li>山田</li>
  </ul>
</div>

liの2番目の要素を取り出したいときはこんな感じの指定になります。

  • CSS: ‘div ul li:nth-child(2)’
  • XPath: ‘//div/ul/li[2]’

これくらい簡単な場合だと手入力でも大丈夫ですが、昔のtableレイアウトのように何重にもタグが重なっていると結構大変です。

そういう時に「Copy CSS path」(Copy XPath)を使うと一発で上記の指定が取り出せます。

手順

20150228_01
手順の様子(クリックで拡大します)

  1. Chromeでディベロッパーツールを起動(Ctrl+Shift+Iまたは「メニュー」→「その他のツール」→「ディベロッパーツール」)
  2. 「Elements」タブを展開
  3. 左上の虫眼鏡アイコンをクリック
  4. 抽出したい要素を表示画面上でクリック
  5. 抽出したい要素のhtmlの部分が展開
  6. 展開した要素で右クリック
  7. メニューの「Copy CSS path」「Copy XPath」を選択
  8. 貼り付けたいソースにペースト

上の画面は上記の7の部分の例となります。(ぼくの場合はブラウザ上で抽出したい要素で右クリックして「要素を検証」ボタンを押しています。そうすると5の所まで一気に行けるので便利です。)

この手順で一気にスクレイピングなどで指定したい記述が一気に取り出せます。

例えば、rubyのNokorigiでヤフーのニュースをピックアップするrubyスクリプト(a.rb)です。

require 'open-uri'
require 'nokogiri'

ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)'
html = Nokogiri::HTML(open('http://yahoo.co.jp', 'User-Agent' => ua))

# CSSバージョン
html.css('#topicsfb > div.topicsindex > ul.emphasis > li').each do |li|
    puts li.text.strip
end

# XPathバージョン
html.xpath('//*[@id="topicsfb"]/div[1]/ul[1]/li').each do |li|
    puts li.text.strip
end

要素の指定の部分を上の手順で抽出して、最後のliだけ1か所の指定からli全要素に変更しました。

$ ruby a.rb

これでヤフーのニュースが出力されます。

注意点

実はこの方法ではまったのでこの記事を書きました(^^;

「Copy CSS path」(Copy XPath)はとても便利なのですが、Chromeが賢いのでちょっと困ることがあります。それはChromeが勝手にhtmlを補修してしまうということです。具体例がわかりやすいのでそれで説明します。

もともとのhtml

<table>
  <tr><td>1</td><td>2</td></tr>
  <tr><td>3</td><td>4</td></tr>  
</table>

Chromeのディベロッパーツール上

<table>
  <tbody>
    <tr><td>1</td><td>2</td></tr>
    <tr><td>3</td><td>4</td></tr> 
  </tbody>
</table>

この例のように勝手にtbodyタグを挿入してしまうのです。この影響でCSSやXPathを抽出した際にもtbodyの記述が入ってきます。

例えば、表の”3″を取り出したいときCopy CSS pathを使うと

  • CSS : ‘table > tbody > tr:nth-child(2) > td:nth-child(1)’
  • XPath : ‘/table/tbody/tr[2]/td[1]’

ところが、通常スクレイピングする場合は生のhtmlを取り出してきているので、要素を抽出する際にtbodyの記述が入ってしまうと、もともとのhtmlにはそのような要素がないため狙った要素が抽出できません。

正しくはtbodyを取り除いた下記になります。

  • CSS : ‘table > tr:nth-child(2) > td:nth-child(1)’
  • XPath : ‘/table/tr[2]/td[1]’

実はこれに気が付くまでかなり時間がかかってしまったので、注意メモとしてこの記事を残します。