iLog

About

Haskellで簡単Webクライアント - http-conduit, html-conduit, xml-conduitを使ってみよう

2015.10.13 Haskell

はじめに

こんにちは、ishiy(@ishiy1993)です。

今日はHaskellで簡単なWebクライアントを作ってみます。http-conduit, html-conduit, xml-conduitのはじめの一歩です。

簡単Webクライアント

どんなアプリを作ってみるかというと、このブログの記事一覧をダウンロードし記事の総数と記事のタイトル一覧を出力するというものです。自分がいま何記事くらい書いたのか気になったのでちょっと作ってみたという話です。

とりあえずソースコードはこんな感じです。

実行するときは

$ stack runghc simple-client.hs --package http-conduit html-conduit xml-conduit text

とします。http-conduitなど必要なパッケージがすでにインストールされていれば--package以下は付けなくてもよいです。stackがインストールされていない場合はこちらを参考にインストールしてみてください。

では、コードを順にみていきます。

まず10行目ですが、simpleHttp関数でこのブログの記事一覧のページを取得してそれをparseLBS関数でByteString型からDocument型に変換しています。simpleHttp関数はNetwork.HTTP.Conduitモジュールの関数で引数に与えたURLのページを取得してきてByteStringとして出力してくれるものです。

11行目でHTMLを解析するためにDocument型からCursor型に変換しています。12行目でHTMLの中から記事のタイトルを抜き出しています。pickUpEntry関数はあとで解説します。

あとは13行目で記事数を数え、15行目で記事のタイトルを整形しています。

最後にこのアプリの肝となっているpickUpEntry関数を解説します。この関数はHTMLを解析して記事のタイトルをリストにする関数です。HTMLの解析にはText.XML.Cursorモジュールの関数を色々使ってます。その中から($//), (>=>), (&//)の3つをみていきます。まず(>=>)はMonadic関数の関数合成演算子です。これは型をみれば明らかですね。

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c

pickUpEntry関数の中に使われているelement関数などはAxis型(もしくはAxis型に類似した型)であり、Axis型は

type Axis = Cursor -> [Cursor]

で定義されていてリストはモナドなのでこれらの関数を(>=>)で合成できるわけです。($//)(&//)はそれぞれ適用演算子と合成演算子です。($//)はCursorにAxisを適用します。とりあえずCursor=HTML,Axis=解析器と考えておいてください。一方で(&//)は2つのAxisを1つのAxisに合成するものです。pickUpEntry関数のイメージは

pickUpEntry r = r(HTML) $// (HTMLの中から要素を選択) &// (その要素の内容を取り出す)

という感じです。この「HTMLの中から要素を選択」する関数が(>=>)を使って組み立てられています。さらに「HTMLの中から要素を選択」する関数と「その要素の内容を取り出す」関数が(&//)で合成され1つの解析器になり、その解析器を($//)でHTMLに適用しています。

まとめ

HTMLを解析するところが少しとっつきにくいかもしれませんが、割と直観的に使える感じがします。ぜひトライしてみてください。

参考ページ:

間違いなどありましたら、@ishiy1993に連絡していただけると助かります。

ではでは。