くりぷと日記

活きる技術・スクレイピングで遊んでみよう!

こんにちは!みなさん、トレードしてますか!?

・・・

私はあんまりしておりませんw

いろいろ高騰してた年始はテンションが高かったんですがね、その後は相場が地味であんまり売買する気も起きませんでした。

ですが今月は少しお金に余裕があるので、安くなった今何かを買おうかなと思いました。

問題は、何を元に買う通貨なり銘柄なりを判断するかですね。

スクレイピングとは

昨今データサイエンスとかビッグデータとか言われてますが、 スクレイピングとは大量のWebページから所望のデータを搔き集めること です。

具体的には、複数のWebページのHTMLをダウンロードし、特定のタグに含まれる情報を収集して整理することになります。

似た言葉にクローリングがありますが、これはあるページを起点にリンクを渡り歩いて関連するページを大量にダウンロードすること、と言えると思います。

なので、クローリングしつつスクレイピングをする、という状況も存在しますし、多くの場合そうなるのかなと思いますが、ここではスクレイピングに着目した解説をしてみます。

状況設定

ここでは、次のような状況を考えて見ます。

「相場の上下は通貨の案件(開発の進展や企業との提携など)と連動することがあるみたいだけど、本当かな?色々な通貨の過去〜未来の案件の日付を取得したい!」

これは私自身が最初にスクレイピングをやってみた動機でもありますw

で、対象となるサイトの個々のページは、みんな次のような形をしているとします(すごく単純化した例です)。

 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132
<!DOCTYPE html>
<html>
  <head>
    <title>BTCのイベント</title>
  </head>
  <body>
    <h1>BTCのイベント</h1>

    <article>
      <date>20XX/XX/XX</date>
      <p class="title">
        イベントの名前
      </p>
      <p class="content">
        イベントの内容について
      </p>
    </article>

    <article>
      <date>20YY/YY/YY</date>
      <p class="title">
        イベントの名前
      </p>
      <p class="content">
        イベントの内容について
      </p>
    </article>

    (以下略)

  </body>
</html>

ここから抽出できるデータは、通貨名(ここでは”BTC”)、日付、イベントの名前、内容がありますね。

実は仮想通貨の案件の日付を列記しているサイトはググるといくつかあるのですが、データだけを全部手元に揃えて、別のデータと突き合わせて解析したい!って時には、全てのページをひとつ一つ巡回して目的の部分をコピペするのは大変です。

Ruby + Nokogiri

そこでスクレイピングの登場です。

スクレイピングをするには、基本的に何かしらのプログラミング言語を扱うことになります。

どうやらスクレイピング・クローリングの界隈ではRubyが人気で、Nokogiriというgem(ライブラリ)がよく使われるようですので、これを使っていきます。

インストール

Rubyを使ったことはあるものとします! まだ無い方は、損はないのでちょいと調べてみてください!

gem install nokogiri

(なお、Nokogiriはインストールで躓きがちなことでも有名です。依存しているネイティブライブラリのバージョンが間違っていることが原因のことが多いみたいです。この場合、ネイティブライブラリになるべく依存しない設計のOgaを試して見るのも良いかもしれません。)

いざスクレイピング!

ここでは、さっき示した例のサイトを対象に考えたコードを掲載します。 実際のウェブサイトのスクレイピングでは色々と読み替えが必要になりますが、ここに具体例をそのまま載せて万が一対象サイトにアクセスを集中させてしまってはいけないので、ご了承ください。

スクレイピングをするには、抽出するタグの位置を指定する必要があります。 この指定の方法にはCSSのセレクタXPathなどがあります。

ここではXPathを使います。

抽出したいタグをブラウザで右クリックして検証ツールを開くと、そのタグを特定できるXPathなどをコピーできますので、参考にすると良いでしょう。 ブラウザごとに方法は異なるので、調べて見てください。

 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637
require 'open-uri' # urlをopenするのに必要
require 'nokogiri'

# 対象のURLです。ここからHTMLをダウンロードします。
# マナーとして、複数回アクセスする場合は、負荷をかけすぎないよう間を置くようにしましょう。
url = 'https://coin.example.com/news/BTC'
html = open(url) do |f|
  f.read
end

doc = Nokogiri::HTML.parse(html)

# <article>タグごとに繰り返します
doc.xpath('//article').each do |article|

  data = [
    article.xpath('date'),
    article.xpath('p[@class="title"]'),
    article.xpath('p[@class="content"]')
  ]

  # 指定したxpathが見つからない場合、nilが返って来ます。
  # nilを操作してしまうとエラーが起きるので、nilでないか
  # 確認をしてからテキストを取り出します。
  texts = data.map do |v|
    if v != nil then
      # タブ区切りで出力するため、文章中にあるタブと改行を空白に直します。
      v.text.gsub(/[\t\n]/, ' ')
    else
      "NA"
    end
  end
  
  # 取得したデータをタブ区切りで出力します。
  puts texts.join('\t')

end

以上で、URLから取得したHTMLをスクレイピングしてタブ区切りで出力してみました(これは存在しないサイトを使った例なので、そのまま実行してもエラーが出ると思います)。

カンマ区切りではなくタブ区切りを選んだのは、文章にカンマが入っている頻度よりもタブが入っている頻度の方が低いのと、仮に入っていてもスペースにしてしまえば大抵問題ないからです。

さらに意味のある分析のために!

こんな感じでデータの取得はある程度自動化できますが、「あるページを起点に、リンクされたページ全てを対象にしたい!」となるとクローリングが必要となります。

また、得たデータを可視化したり統計的に解析するには、Rubyでも良いのですが、RやPythonを使う人が多いのかなと思います。

全ての道具に慣れるには時間がかかりますが、そんなに怖いものではないということを伝えられていればいいかなと思います。