しろかい!

アプリ開発や機械学習などの開発Tips.

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

*1:デフォルトの入力形式だとファイルが分割されてしまい xml の形式が崩れてしまいます.この辺は HDFS の仕組みを調べてみてください.