Julia
Webスクレイピング
JuliaDay 23

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

More than 3 years have passed since last update.


はじめに

科学計算向けスクリプト言語「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パーサーが欲しい所です。