MapReduce処理の向き不向き
さて、
MapReduceは計算フレームワークですが、
入力に使用されるデータの種類は
- テキスト
- XML
- バイナリ
- データベースから
という風にいくつかの入力を受け付けることが可能です。今回はテキストファイルを入力としたMapReduceを行いたいと思います。
大規模なテキストデータ
入力となるテキストデータを今回はインターネット上のコンテンツから取得したいと思います。
2ちゃんねるという巨大掲示板サイトは、
インターネットユーザの嗜好に偏った部分もありますが、
今回の題材では、
解析
ある番組に実況データを解析し、
- ある時間単位でどのような単語が多く書き込まれたか?
複数の人間が1つのコンテンツを視聴しているわけですが、
処理の流れ
①データ取得・登録
2ちゃんねるからダウンロードしたログデータをHDFSに保存します。これはMapReduce処理のインプットとなるデータです。ここでは1行1レスポンスというフォーマットで保存します。
②Map処理
①のデータを入力としてMap処理がスタートします。Map処理では、
- データの正規化
(アスキーアートの削除) - キーとバリューへの分割
(unixtimeを10分で丸めた値をキー、 品詞解析した単語をバリューにする)
この処理は各サーバに分割されたファイルについて実行されます。
③Reduce処理
②で処理された結果を受けて実行されます。キーごとに単語数を集計し、
基本的には上記のような流れで進めてみたいと思います。
データフォーマット
2ちゃんねるのデータは以下のような形式になっています。
- 文字コードはUTF-8
- CSV形式
- 行セパレータは\nとする
(改行区切り)。
例)
1283124797,4,名無しでいいとも!,y+yK12Lz,,sage, 絵心があるなw
左から、
書き込みunixtime
レス番号
名前
ID
ID2
メールアドレス
書き込みテキスト
データ取得プログラム
#!/usr/bin/perl
use strict;
use WWW::2ch;
use Data::Dumper;
use Encode;
use Encode::Guess qw/ euc-jp shiftjis 7bit-jis /;
my $ch2url = {
1=>"http://hayabusa.2ch.net/livenhk/","http://hayabusa.2ch.net/livenhk/",
2=>"http://hayabusa.2ch.net/liveetv/","http://hayabusa.2ch.net/liveetv/",
4=>"http://hayabusa.2ch.net/liventv/","http://hayabusa.2ch.net/liventv/",
6=>"http://hayabusa.2ch.net/livetbs/","http://hayabusa.2ch.net/livetbs/",
8=>"http://hayabusa.2ch.net/livecx/","http://hayabusa.2ch.net/livecx/",
10=>"http://hayabusa.2ch.net/liveanb/","http://hayabusa.2ch.net/liveanb/",
12=>"http://hayabusa.2ch.net/livetx/","http://hayabusa.2ch.net/livetx/",
};
my $url = $ch2url->{$ARGV[0]} or die "引数にチャンネル番号を入れてね";{$ARGV[0]} or die "引数にチャンネル番号を入れてね";
my $bbs = WWW::2ch->new(url => $url, cache => '/tmp/www2ch-cache');new(url => $url, cache => '/tmp/www2ch-cache'); $url, cache => '/tmp/www2ch-cache'); '/tmp/www2ch-cache');
$bbs->load_setting;load_setting;
$bbs->load_subject;load_subject;
#print STDERR Dumper $bbs->subject;subject;
foreach my $dat ( $bbs->subject->threads )subject->threads )threads )
{
# threadのキー
my $key = $dat->key;key;
my $title = $dat->title;title;
&u8(\$title);
$dat->load;load;
foreach my $res ( $dat->reslist )reslist )
{
my $resid = $res->resid;resid;
my $body = $res->body_text;body_text;
my $name = $res->name;name;
my $time = $res->time;time;
my $be = $res->be;be;
my $mail = $res->mail;mail;
my $id2 = $res->id;id;
&u8(\$resid);
&u8(\$body);
&u8(\$name);
&u8(\$mail);
$body =~ s/\n//g;
print $time,",",$resid,",", $name, ",", $id2,",", $be, ",", $mail,",", $body, "\n";
}
}
sub u8
{
my ($t) = @_;
Encode::from_to($$t, "shiftjis", "utf8");
}
データ取得方法
$ ./2ch.pl 4 > 2ch_4.csv 2ch_4.csv
このように引数にチャンネル番号を指定して起動します。標準入力に出力されますので、
HDFSへのデータ登録
hユーザで登録を行います。
$ hadoop dfs -put 2ch_4.csv
これでHDFSにデータの登録ができました。
データの確認
$ hadoop dfs -ls drwxr-xr-x - h supergroup 4123 2010-10-12 16:53 /user/h/2ch_4.csv
このような出力が出れば問題ありません。
$ hadoop dfs -cat 2ch_4.cvs
とするとファイルの中身が出力されると思います。
取り急ぎ今回はここまで。次回から実際にプログラムを書いていきます!