HadoopStreaming で xml ファイルを処理する
HadoopStreaming で xml ファイルを扱う方法の解説です.
この記事では,しろかい!のRSSフィードから <title>
~</title>
を抽出することを目標とします.
また,言語は Python を使用します.
実装にあたっては以下の記事を参考にしました(英語です).
http://davidvhill.com/article/processing-xml-with-hadoop-streaming
RSSフィードを取得してHDFSに転送
$ wget http://shirokai.hatenablog.com/feed -O feed.xml $ hadoop fs -put feed.xml
mapper.py
<entry>
~</entry>
間をまとめた後,xml をパースして <title>
~</title>
を出力します.
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import cStringIO import xml.etree.ElementTree as xml # <entry>~</entry>の文字列を保持するバッファ buff = None # <entry>~</entry>間を処理中ならTrue intext = False for line in sys.stdin: line = line.strip() # <entry>の開始.buffに書き込める状態にする. if '<entry>' in line: buff = cStringIO.StringIO() intext = True # <entry>~</entry>間.buffに書き込み. if intext: buff.write(line) # </entry>.xmlパースして<title>~</title>を出力,buffは解放. if '</entry>' in line: root = xml.fromstring(buff.getvalue()) print root.find('title').text.encode('utf-8') buff.close() buff = None intext = False
reducer.py
Mapperの出力をそのまま出力するだけです.
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys for line in sys.stdin: print line.strip()
HadoopStreaming の実行
$ hadoop jar hadoop-streaming-***.jar -mapper mapper.py -reducer reducer.py -file mapper.py reducer.py -input feed.xml -inputreader "StreamXmlRecordReader,begin=<entry>,end=</entry>" -output feed.out
※ ***
には使用するバージョンが入ります.
-inputreader
オプションで,Mapper への入力形式を指定できます.
入力を xml にするには StreamXmlRecordReader,begin=<entry>,end=</entry>
を指定します.これで,xml の<entry>
~</entry>
間を1つのかたまりとして同一の Mapper で処理されるようになります*1.
結果を確認
$ hadoop fs -cat "feed.out/*" 【Mac】「Get Plain Text」でEvernoteへのコピペが捗る! Rails Tutorial 全部読んだので感想とかまとめとか LIBLINEARのパラメータをグリッドサーチするスクリプト書いた ... 以下略 ...
ちゃんと <title>
~</title>
を取り出せました!
まとめ
HadoopStreaming で xml ファイルを扱う方法を解説しました.
この記事で扱ったように,xml を扱うには少し工夫が必要です.
そこさえ気をつければ大規模な xml ファイルも Hadoop で高速に処理することができます.
例えば Wikipedia の dump ファイルを処理する時なんかに役立つと思います.
機会があれば是非試してみてください!
Wikipedia:データベースダウンロード - Wikipedia