search
LoginSignup
25

More than 5 years have passed since last update.

posted at

updated at

Juliaで楽しくWebスクレイピング!

はじめに

科学計算向けスクリプト言語「Julia(JuliaLang)」の利点の一つは、
データ前処理と統計処理、そしてその結果のレポートを、Pythonと同じように一貫して行える事にあります。
そして、Juliaは多くのケースでPythonよりも早いと言われています。
しかし、Juliaの最新バージョンは0.4であり、
ライブラリが出揃っている状態ではなく、又、ライブラリの情報も知れ渡っているものではありません。
今回は、JuliaでWebスクレイピング(Webページからデータを抽出する事)に使えそうなライブラリを調べてみました。
(Beautiful SoupをPyCall.jlで使う方法も考えましたが、今回は紹介しません)

01.Webページをダウンロードする。 [Requests.jl, HttpCommon.jl]

Requests.jlの関数「get(URI, クエリ文字列)」でWebページをダウンロードします。
その際、HttpCommon.jlの関数「encodeURI(エンコード前の文字列)」でWebページのURIをエンコードしておきます。
getの返り値のメンバー変数「data」からソースコードを読み取ります。

Webページをダウンロードする.jl
Pkg.add("Requests")
Pkg.add("HttpCommon")

using Requests
using HttpCommon

request = get("http://www.nicovideo.jp/search/" * encodeURI("東方project"), query = {:hft => "0", :itc => "1", :ct => "2", :cip => "1"})
code = request.data

02.Webページのソースコードを解釈する。[Gumbo.jl]

Gumbo.jlのparsehtml(HTMLの文字列)でソースコードを解釈します。
Gumbo.jlはHTML構文解析ライブラリGumbo(Google製)のJuliaラッパーです。

ソースコードを解釈する.jl
Pkg.add("Gumbo")

using Gumbo

doc = parsehtml(code)

03.指定要素を取得する。

Gumbo.jlで要素を取得する方法は、
ジャグ配列(配列の配列)として指定する方法とイテレーターの中で指定する方法の2つがあります。
CSSセレクターやXPathのような高度な指定方法はないようです。

ジャグ配列として指定する.jl
elem = doc.root[2][7][1]
elem
  # => HTMLElement{:div}:
  #    <div class="inner"> ……
イテレーターの中で指定する.jl
for elem in preorder(doc.root)
  if isa(elem, HTMLElement)
    #タグの場合
    #(特になし)
  elseif isa(elem, HTMLText)
    #テキストの場合
    println(elem.text)
      # => キーワードで動画検索
      #    niconico ……
  end
end

※イテレーター自体の指定方法はpostorder(前から)・preorder(後ろから)・breadthfirst(幅優先)の3つがあります。

04.指定要素を判別し、値を取得する。

要素にはHTMLElement(タグ)とHTMLText(テキスト)の2種類の型があるようです。
それぞれの型で値を取得する方法は違っています。

HTMLElementから値を取得する.jl
#タグ名を取得
tag(elem)
  # => ;div

#属性一覧を取得
elem.attributes
attrs(elem)
  # => Dict{String,String} with 1 entry:
  #      "class" => "inner"

#子要素一覧を取得
elem.children
children(elem)
  # => 2-element Array{HTMLNode,1}:
  #     HTMLElement{:div}
  #     HTMLElement{:div}

#親要素一覧を取得
elem.parent
  # => HTMLElement{:section}:
  #    <section class="tagCaption"> ……

#属性を取得
getattr(elem, "class")
  # => "inner"

#属性を設定
setattr!(elem, "id", "divInner")
  # => "divInner"
HTMLTextから値を取得する.jl
txt = doc.root[2][7][1][1][1][1][1][1]

#テキストを取得
txt.text
  # => "Example text"

終わりに

PythonのBeautiful Soupのような高度なHTMLパーサーが欲しい所です。

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
What you can do with signing up
25