知っておくとちょっとだけ捗るかもしれないzshの便利機能

たまたまTwitterで見かけたのですが、zshってこんなこと出来るんですね。

適当に、似た構成のディレクトリを作ります。

$ mkdir -p hoge/{foo1,foo2}/bar

これで、以下のようなディレクトリが生成されました。

~/hoge/foo1/bar
~/hoge/foo2/bar

このとき、例えば ~/hoge/foo1/bar にいるとして、そこから ~/hoge/foo2/bar にはこんな感じで移動できるみたいです。知らなかった〜。

$ pwd
/Users/sasata299/hoge/foo1/bar

$ cd foo1 foo2 # カレントパスのfoo1をfoo2に変えたディレクトリに移動

$ pwd
/Users/sasata299/hoge/foo2/bar

AWS Lambdaを使ってサーバレスでテキスト抽出するぞ!という気持ち

この記事は 今年もやるよ!AWS Lambda縛り Advent Calendar 2015 の23日目です。

「何か書くぞ!」と思いエントリーしてみたもののどうしよう、、と思っていたのですが、そういえば個人的に Apache Tika というのが最近気になっていたので使ってみることに。

Apache Tika

これは、PDFやエクセル等のファイルから、テキストデータやメタデータを抽出してくれるという便利ライブラリです。これを使って、ファイルが登録されたら裏でテキストデータを抽出して、それを全文検索で引っかかるようにする…みたいなことが出来ると楽しそうです。

Apache Tika自体はJavaのライブラリなのですが、Node.jsから扱うためのライブラリ があったので、今回はこれを使って

1. S3にPDFファイルが置かれる
2. それをトリガーとしてLambdaが起動し、Apache Tikaを使ってテキストデータを抽出する
3. 抽出したテキストデータをS3に置く

という流れをやってみたいと思います。

Lambdaを触ってみる

では早速、AWSのマネジメントコンソールからLambdaを触ってみましょう。

(クリックで拡大されます)
Step1

今回はS3にファイルが置かれたのをトリガーとしてLambdaを起動したいので、"s3" というキーワードでフィルタリングした状態です。Node.jsである一番右側の「s3-get-object」を選びました。
※ちなみにblueprintは、青写真とか設計図とかいう意味

次は、event source(トリガー)の指定です。今回はPDFファイルの作成や更新時にのみ、Lambdaを起動させるようにしました。

Step2

続いて、Lambda起動時に実行される処理を登録します。今回は10MBを超える容量となったので、S3に必要なファイルをまとめてzipにしたものを置いておき、それを取り込むようにします(後述します)。

Step3

LambdaにはIAMのロールを設定する必要があるので適切なロールを設定してください。今回はS3へのアクセスができるようになっていれば良いかと思います。

Step4

トリガーの反映は後で良いでしょう。基本的にはテストデータで動作確認して、動くようになったらトリガーをONにし、実際にS3にファイルが置かれたことをトリガーとしてLambdaが起動するようにします。

テキストデータの抽出

さて、いきなり結論となってしまいますが、今回はこんなコード(index.js)を書きました。

console.log('Loading function');

var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });

var tika = require('tika');

exports.handler = function(event, context) {
    console.log('Received event:', JSON.stringify(event, null, 2));

    var bucket = event.Records[0].s3.bucket.name;
    var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
    var params = {
        Bucket: bucket,
        Key: key
    };
    s3.getObject(params, function(err, data) {
        if (err) {
            console.log(err);
            var message = "Error getting object " + key + " from bucket " + bucket +
                ". Make sure they exist and your bucket is in the same region as this function.";
            context.fail(message);
        } else {
            console.log('CONTENT TYPE:', data.ContentType);
            console.log('KEY:', key);

            var url = "https://s3-" + event.Records[0].awsRegion+ ".amazonaws.com/" + bucket + "/" + key;
            console.log(url);

            // テキストデータの抽出
            tika.text(url, function(err, text) {
                if (err) {
                    context.fail(err);
                } else {
                    s3.putObject({
                        Bucket: bucket,
                        Key: key + ".txt", // S3にUPするファイル名
                        Body: text
                    }, function(err, data) {
                        if (err) {
                          context.fail(err);
                        } else {
                          context.succeed("Successfully finished");
                        }
                    });
                }
            });
        }
    });
};

テキストデータの抽出のところ、びっくりするくらい簡単に出来るので拍子抜けです。ただこれ、最終的にはLambda上で動かせてません。。(ローカルでは動くんですが><)

なお事前に、

$ npm install aws-sdk --save-dev
$ npm install tika --save-dev

は実行済みです。その後、index.jsとnode_modulesをzipに固めて、S3に置いてLambdaの起動時の処理として登録しています。最終的に50MBほどのサイズになってました。

$ zip -r extract_text_data.zip index.js node_modules

S3のバケットポリシー

今回はLambdaからS3に置かれた任意のファイルにアクセスしてテキストデータの抽出をするので、バケットごと誰でも読み取りができるようにしています。。><

S3のバケットポリシー

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "AddPerm",
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::<bucket_name>/*"
		}
	]
}

<参考URL>
S3のアクセスコントロールが多すぎて訳が解らないので整理してみる | Developers.IO


・・さて、そんな感じで結局はうまくいっていないんですが、一応遭遇した問題を残しておきます。m(_ _)m

遭遇した問題その1

トリガーをONにしようとしたら、

There was an error creating the event source mapping: Configuration is ambiguously defined. Cannot have overlapping suffixes in two rules if the prefixes are overlapping for the same event type.

こんなエラーが出てきてトリガーがONにできず困りました(どういうことなの???)。でも次の日またやってみたらいけた。なんだったんだろうか。。

遭遇した問題その2

Lambdaで実行していたら、invalid ELF header というエラーが!!どうも調べてみると、LambdaはLinux上で動作するっぽいんですが、Macでコンパイルしているため、Linux上でそれが正しく動かないのが問題のようです。

解決策としては、AWSのAmazon LinuxのEC2上でコンパイルしようという話のようなので、そりゃそうだと思いつつ実際に試してみました。が、それを使うと今度はこんなエラーが。。(解決できず)

libjvm.so: cannot open shared object file: No such file or directory

結局は動かせてないし時間が無くてバタバタなんですが、何かの参考になれば幸いです。

Mroongaの導入事例を話してきました #groonga

もうすっかり冬ですね。

良い肉の日(11/29)に開催された Groonga Meatup でMroongaの導入事例を話してきました。
全然詳しくないんですが、発表するといろいろ教えてもらえて良いですね! :)

Git管理下で複数のファイルを一括置換したい

「hogehoge」を「ほげほげ」に変更したのでそのときのメモです。Git で管理していたファイルが対象だったので、以下のようにしました。

$ git grep -l 'hogehoge' | xargs sed -i -e 's/hogehoge/ほげほげ/g'

git grep 'hogehoge' で hogehoge を含むファイルパスとその内容が表示されるんですが、そこに -l オプションを付けると、ファイルパスだけを表示することが出来るので便利です〜

それを xargs で sed に渡して一括で置換しています。普段は -i オプションでバックアップファイルの拡張子を指定したりしますが、Git で管理されているので付けてません。

Rails開発をする上で知っておいた方が良さそうなこと

先週の木曜日、Speeeさんで開催された第2回SpeeeTeckPartyにお邪魔して発表してきました。

これは食 x 技術をテーマにした勉強会で、第1回は「寿司 x Ad」だったそうなんですが、なんでも今回は「からあげ x Ruby」だそうで、であればささたつさんしかいない!という人選だったそうですw
(お寿司食べたかったな・・w

というわけで、Rails開発するなら知っておくと良さそうなことを10個(質疑応答で一つ増えて11個になったりもしましたが!)紹介してきました。以下がスライドです。



他にもいろいろとあると思いますが、少しでも役に立てば幸いです :D
karaage299 at gmail.com




寄稿した記事

Ruby Freaks Lounge (28,30)
NoSQLを試してみる

作ったもの

カープ戦速報ボット
まとめったー
YouTube Oricon Ranking
NicoNicoブックマーク
ねたばれ見る?


ブックマーク数



購読者数



 
RSS登録
Subscribe with livedoor Reader