HTMLパーサ
HTMLパーサに今まではTagSoupを使っていたんですけど、IOまわりをConduitで書き直してるついでになんか別のConduit対応パーサを使ってみようかなと思ってちょっと調べてみました。
とりあえず一番簡単というか最初に目についたのはhtml-conduitのsinkDocを使う方法。
import Data.Conduit import qualified Data.Conduit.Binary as CB import qualified Text.HTML.DOM as DOM main :: IO () main = do doc <- runResourceT $ CB.sourceFile "test.html" $$ DOM.sinkDoc print doc
Text.XML.Documentが返ってくるので、あとは頑張りましょう。これほとんどxml-conduitじゃないか。
それと、同じモジュールのeventConduitを使う方法。
import Data.Conduit import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL import qualified Text.HTML.DOM as DOM main :: IO () main = do doc <- runResourceT $ CB.sourceFile "test.html" $= DOM.eventConduit $$ CL.consume print doc
これはConduitなので、なんか適当にconsumeしてもいいし、ちょっと使い勝手がいい気がする。
html-conduitを入れた時に入ったっぽいTagStreamでもだいたい似たようなことができるけど、こっちの方が使いやすそうな気がする。いや同じか。まあどっちでもいいかんじです。
import Data.Conduit import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL import Text.HTML.TagStream main :: IO () main = do doc <- runResourceT $ CB.sourceFile "test.html" $= tokenStream $$ CL.consume print doc
あとは、Text.HTML.TagStream.Parserを使って自分でパーサを組み立てる手もある。
このあたりは、Attoparsec用のHTMLパーサ関数ライブラリのようで、Data.Conduit.Attoparsec.sinkParserとかと組み合わせて使うんじゃないでしょうか。たぶん。
sinkDoc以外のやつらが結構使えるんじゃないかと思ってるんですが、別に今回は実装したわけでもないし、評価したわけでもないし、あーでもtagstreamが一番プリミティブっぽいからこの場合は無難かもなぁと思ったくらいで、あんまし意味は無いです。評価順を考えると実はどっちも大して変わらないのかもしれない。結局みんなTagStream.Parserにいきつくっぽいし、eventConduitかtokenStreamあたりがちょうどいいんじゃないでしょうか。
それはそうと今更ですがConduit.Listってかなり便利ですね。