LoginSignup
43
44

More than 5 years have passed since last update.

CasperJSでWEBサイトをスクレイピングしてみる

Last updated at Posted at 2014-07-11

前回の投稿(CasperJSでWEBサイトの画面キャプチャを取得してみた)の続きです。環境構築の方法(Mac)については、前回の投稿をご覧ください。

はじめに

  • とある事情で、Qiitaの Organizationページ(自社の) をWEBスクレイピングしました。
    • とある事情というのは、自社のブログ に、自社メンバーのQiita新着投稿をブログパーツ的に表示したかった。
    • Qiitaへゴリゴリ負荷をかけるものではないです^^;
  • CasperJS は CoffeeScript をそのまま解釈してくれるので、今回は CoffeeScript で書いてみます。
    • ちなみに CasperJS は仮想ブラウザ?的に動いているので、対象ページが JavaScript 等で動的に描写されるページでも、スクレイピングできるはず..です。

今回の成果物

簡単なWEBスクレイピングの例

  • まず手始めに、対象ページの a タグの href="hoge" を全て取得してみます。ソースはこんな感じ。

    scraping.coffee
    casper = require("casper").create()
    
    target_url = "http://qiita.com/organizations/yumemi"
    
    # 対象のWEBページを開く
    casper.start target_url, ->
    
      urls = []
    
      urls = @evaluate ->
        items = document.querySelectorAll("a")
        Array::map.call items, (e) ->
          e.getAttribute('href')
    
      # 出力
      @echo(urls.join("\n"))
    
    casper.run ->
      @exit()
    
  • では上記のソースを実行してみます。コマンドラインで、

    $ casperjs scraping.coffee
    
  • すると次のように、href="hoge" の中身が全て取得できたことが確認できます。

    スクリーンショット 2014-07-11 16.47.34.png

querySelector の使い方のポイント

上記の例のように、単純に a タグのものを全て取得としてしまうと、余分なものも取得されてしまうので、実際は対象ページのHTMLの構造を見て、絞り込む必要があります。

具体的にいうと、divタグのid名class名HTMLタグ名HTMLタグの属性(検索に正規表現の利用可) で絞ります。

例えばこの例だと、

elements = []

elements = @evaluate ->
  items = document.querySelectorAll(".activities article .body a[href*=\"/items/\"]")
  Array::map.call items, (e) ->
    e.getAttribute('href');
  • 対象ページのHTMLの activities class 配下の、
  • article タグ 配下の、
  • body class 配下の、
  • a タグで、href 属性の value(つまりURL)で /items/ を含むものの、
  • href 属性の value(つまりURL)を取得する

となります。

href 属性のところで *= は部分一致を意味します。もし先頭文字列の一致の場合は ^= 、後方文字列の一致の場合は $= とします。

e.getAttribute('href'); は属性の取得を意味します。もしHTMLの中身を取得する場合は e.innerHTML とします。

ただ実際には、うまく絞りきれない場合が多いので.. その場合は、いったん配列にスクレイピングの結果を格納しておいて、普通に CoffeeScript で配列操作を行います。例えば、

  • 特定のURLを含むものを、別の配列へ移し替える

    • この例の場合は URLが /piyo から始まるもの
    elements_2 = []
    
    i = 0
    while i < elements.length
      if elements[i].match(/^\/piyo/)
        elements_2.push(elements[i])
      i++
    
  • 文字列を加工する

    • この例の場合は、余分な文字列の削除
    i = 0
    while i < element.length
      entry_days[i] = entry_days[i].replace(/[\n\r]/g,"")
      entry_days[i] = entry_days[i].replace(/\ /g,"")
      entry_days[i] = entry_days[i].replace(/<strong>.+?<\/strong>/g,"")
      i++
    

おわりに

スクレイピングする際は、対象ページのHTMLソースを見て、睨めっこ&試しながらソースを書いていく流れになります^^; 結構、骨が折れる作業です..

43
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
44