48
S wonderdriving.com ブブブブブブブブブブブ Data API ブブブブブブブ ブブブブブブブブブブ ブブブブ 1

ブログメディアにおけるData APIの活用について

Embed Size (px)

Citation preview

Page 1: ブログメディアにおけるData APIの活用について

1

S

wonderdriving.comブログメディアにおけるData API の活用について

ワンダーツー株式会社上野初仁

Page 2: ブログメディアにおけるData APIの活用について

2

本日の内容

自己紹介(個人、会社)

wonderdriving.com とは

Data API と wonderdriving.com

人気記事ランキングスクリプト

アセット登録スクリプト

Data API 2.0 対応

今後

Page 3: ブログメディアにおけるData APIの活用について

3

S

発表者 自己紹介

Page 4: ブログメディアにおけるData APIの活用について

4

上野初仁 a.k.a. @uehatsu

twitter : @uehatsu

現 Wonder2 Inc. エンジニア UNIX, Apache, MySQL, Perl, PHP, JavaScript, Rails,

Objective-C, Swift, etc. フルスタックエンジニアという名の何でも屋

(自分で言うなと、、、)

元 Six Apart エンジニア 2003 - 2011 TypePad (現 lekumo )チーム Movable Type チーム

Page 5: ブログメディアにおけるData APIの活用について

5

趣味

コンピュータ全般

DTM TM Network カバー

OED C4U (Crazy for you)http://youtu.be/og0W4Mp3QC0

Perfume カバーチョコレイト・ディスコhttp://youtu.be/393kJwne88E

soundcloudhttps://soundcloud.com/uehatsu

Page 6: ブログメディアにおけるData APIの活用について

6

SA 時代に自分の残した物

Movable Type 開発者向けガイドhttps://github.com/movabletype/Documentation/wiki プラグイン開発ガイド MTML ガイド

今でも自分で良く使います プラグイン開発ガイドは、関根元和さん( CHEEBOW さ

ん)の「 Movable Type プラグイン開発入門」を MT5 の流儀( config.yaml など)に対応、拡張させたドキュメント

MT6 でも使えます、 PSGI 周りとか書き足したいなぁ、、、

Page 7: ブログメディアにおけるData APIの活用について

7

S

Wonder2 Inc. 紹介

Page 8: ブログメディアにおけるData APIの活用について

8

ワンダーツー株式会社 会社概要

代表者 代表取締役 野間恒毅

設立 2011/04/25

資本金 300 万円

主な事業内容 システム開発、 Movable Type 開発・カスタマイズ、スマートフォ

ンアプリ開発、メディア事業、コンサルティング

加盟団体 ProNet Japan (Six Apart Co. Ltd.)

Page 9: ブログメディアにおけるData APIの活用について

9

ワンダードライビング(運営:ワンダーツー)

ブログメディア(車、ホビー、 etc. )

Movable Type 6

http://wonderdriving.com/

Page 10: ブログメディアにおけるData APIの活用について

10

株式会社アドヴァン

EC サイト

Movable Type 5 +MT コマース

http://www.advan.co.jp/

Page 11: ブログメディアにおけるData APIの活用について

11

ハジー物産株式会社

商品紹介サイト

Movable Type 5

http://hagypack.com/

Page 12: ブログメディアにおけるData APIの活用について

12

株式会社シーフォ

会社紹介、メディア

Movable Type 5 +ソーシャルメディア運用

http://www.sifo.jp/

Page 13: ブログメディアにおけるData APIの活用について

13

iPhone アプリ レーダーマップ

位置がわかるだけのシンプルな iPhone アプリ

ID 不要、登録不要

匿名利用

その他にも iPhone アプリ受託開発も行っています

Page 14: ブログメディアにおけるData APIの活用について

14

S

wonderdriving.comとは

Page 15: ブログメディアにおけるData APIの活用について

15

ワンダー・ドライビングとは

スーパーカーからラジコン、ミニ四駆、美女まで男の子の夢もりだくさん「ワンドラ」 車、バイク、ラジコン、ミニ四駆、ボート、ガジェット、

美女、などホビー全般についてのオウンドメディア 弊社野間やゲストブロガーの方々による更新 特にミニ四駆、ラジコン、車のショーレポートなどのコン

テンツが人気

Page 16: ブログメディアにおけるData APIの活用について

16

ワンドラが SA 導入事例に紹介されました

Six Apart 社の導入事例にワンドラが紹介されました。

http://www.sixapart.jp/business/wonder2.html

Page 17: ブログメディアにおけるData APIの活用について

17

S

Data API とワンドラ

Page 18: ブログメディアにおけるData APIの活用について

18

Data API を積極導入する事になったきっかけ

ワンドラ リニューアルのタイミングが MT6 発表とほぼ同タイミングだったこと

リニューアル時に PV ランキングのウィジェットデザインがデザイン会社からアップされたが、この時点で未実装だった

Page 19: ブログメディアにおけるData APIの活用について

19

旧 PV ランキングページ

デザインリニューアル前の PV ランキングページ Apache 生ログを集計するスクリプトを日に1回程度実行

し、インクルードする HTML を生成していた 処理時間が長時間かかり、実行間隔が長いためデータの即

時性がなかった 別途 Google Analytics でアクセス解析をしていたが誤差

が大きかった

   → リニューアル後は別の方法で作成することに

Page 20: ブログメディアにおけるData APIの活用について

20

新 PV ランキングページ

新デザインになってからしばらくは PV ランキングページはありませんでした 新デザイン移行時に MT6 にアップグレード 弊社野間から「上野さん PV ランキングページ作るスクリプ

ト作って」と話があり、半分冗談で「じゃMT6 の Data APIで作りましょうか、 GA の集計機能あるし」と言ったら、そのまま企画が通る

さくっとツール作成 紆余曲折はありましたが、技術的な話は後ほど、、、

Page 21: ブログメディアにおけるData APIの活用について

21

人気記事ランキングサイドバー

・ 1 位〜 5 位 ・順位 ・カテゴリー ・投稿日 ・タイトル

Page 22: ブログメディアにおけるData APIの活用について

22

人気記事ランキング 一覧

1 位〜 30 位 サムネール 投稿日 順位 タイトル

Page 23: ブログメディアにおけるData APIの活用について

23

S

人気記事ランキングスクリプト

Page 24: ブログメディアにおけるData APIの活用について

24

2つのスクリプト

サイドバーと一覧を作成しているスクリプトは別 作成時間を優先させたため共通化せず

実行間隔 2 つのスクリプトとも 5 分間隔

それぞれインクルードファイルを出力し保存 インクルードファイルを SSI を使って各ページに挿入

Page 25: ブログメディアにおけるData APIの活用について

25

Data API にアクセスするための共通関数

_request() 関数を作成 $content = _request( $method, $api_url, $params,

$token ); $method : ‘POST’, ‘GET’ $api_url : ‘http://foo.com/mt/mt-data-api.cgi/v1/... $params : 例) { username => $user, password => $pass,

clientID => ‘aaaa’ }

$token : accessToken $content : Data API からのレスポンスを

MT::Util::from_json() した戻り値 my $token = $content->{accessToken};

Page 26: ブログメディアにおけるData APIの活用について

26

_request() ver.1 の中身

sub _request { my ( $method, $url, $params, $accessToken ) = @_; if ( $method eq 'GET' ) { $url .= '?' . join( '&', map{ $_ . '=' . $params->{$_}} keys %$params ); } my $request = HTTP::Request->new($method, $url); if ( $accessToken ) { $request->header('X-MT-Authorization' => "MTAuth accessToken=$accessToken"); } if ( $method eq 'POST' ) { $request->content( join( '&', map{ $_ . '=' . $params->{$_}} keys %$params ) ); } my $ua = MT->new_ua; my $res = $ua->request( $request ); unless ( $res->is_success ) { if ( $res->code == 500 ) { my $content = MT::Util::from_json( $res->content ); my $message = $content->{error}->{message}; $message =~ s/\\x{([0-9a-z]+)}/chr(hex($1))/ge; die $message; } else { die $res->as_string; } } return MT::Util::from_json( $res->content );}

Page 27: ブログメディアにおけるData APIの活用について

27

スクリプトの動作

authentication

カテゴリー一覧の取得

PV一覧の取得

エントリーの取得

サムネール URL の取得(サムネールの作成)

HTML の生成

Page 28: ブログメディアにおけるData APIの活用について

28

PV一覧の取得

api_url : http://foo.com/mt/mt-data-api/v1/${blog_id}/stats/path/pageviews startDate, endDate : YYYY-MM-DD, 昨日〜今日に設定 limit : 今回は 200

レスポンスの中に {item} として結果が格納されている

$item->{archiveType} で結果の内容が分かる 今回は個別アーカイブ’ Individual’ のみを対象とした 個別アーカイブのエントリー id は $item->{entry}-

>{id}

Page 29: ブログメディアにおけるData APIの活用について

29

サムネール URL の取得

サムネール URL を取得する API は存在しないため自作 DataAPIAssetInfo プラグイン

エンドポイント (/sites/:site_id/assets/:asset_id/info ) を追加

thumb_width, thumb_height, thumb_square, thumb_scale

アクセスがあると指定のあった Asset のサムネールを作成 実際には MT テンプレートのビルドが走る <mt:Asset id="$asset_id"><mt:AssetThumbnailURL

width="$width" height="$height" square="$square" /></mt:Asset>

Page 30: ブログメディアにおけるData APIの活用について

30

アセットが登録されていないエントリーがたくさん

エントリーアセットが未登録の物はデフォルト画像(ワンドラロゴ)が表示される

リニューアル前はアセットに画像を登録していなかった flickr に画像をアップし、そこでタグを生成して貼り付けて

いたため、アセットに登録していなかった ランキングは古いエントリーが出る事が多かったためロゴ画像がずらっと並ぶ残念なことに

「過去画像アセットに登録できたらいいですねー」「じゃ作って」「(えっ?!)」で作成する事に

Page 31: ブログメディアにおけるData APIの活用について

31

S

アセット登録スクリプト

Page 32: ブログメディアにおけるData APIの活用について

32

アセット登録スクリプト

アセット登録をするだけなら Data API を利用する必要は無いけど、、、 外部ファイル( flickr画像)を MT にアップロードしてア

セットとして登録 そのアセットをエントリーアセットとして登録 デザインの関係でカスタムフィールド画像も同時に登録し

たい   →トータルで考えて Data API で作るのが早そう

Page 33: ブログメディアにおけるData APIの活用について

33

スクリプトの動作

authentication

エントリーの取得(複数エントリーを一括取得)

本文、追記を HTML::TagParser で解析し img タグを抽出

img タグの src が flickr の物だったらダウンロード

Data API を使って画像をアセットとしてアップロード

エントリーアセットとして登録

カスタムフィールド画像として登録

Page 34: ブログメディアにおけるData APIの活用について

34

ファイルアップロード用に_request() 関数を変更

request作成に HTTP::Request::Common の GET と POSTを利用するように変更

$params = { path => $upload_path, file => [ $save_path ], autoRenameIfExists => 1 };

path : ${WEB_ROOT} からのアップロード先のパス file : ダウンロード済みの flickr画像の保存先パス、 [ ] で囲む autoRenameIfExists => 1 : 既に存在していた場合自動でリネームした上でアップロード

$request = POST( $url, Content_Type => 'form-data', Content => $params );

Page 35: ブログメディアにおけるData APIの活用について

35

エントリーアセットとして登録

アセットをエントリーに紐付ける機能がないため自作 DataAPIAssetInfo プラグインを拡張 /sites/:site_id/assets/:asset_id/set_entry my $params = { entry_id => $entry_id }; これを MT::ObjectAsset->get_by_key() で

object_asset を取得し save

Page 36: ブログメディアにおけるData APIの活用について

36

アセットを登録するコード

本来なら entry_id の存在チェックなどする必要がありますが、ある物としてコードを書いています。

my $object_asset = MT::ObjectAsset->get_by_key({ asset_id => $asset->id, blog_id => $blog->id, object_ds => 'entry', object_id => $app->param('entry_id'), }); $object_asset->save();

Page 37: ブログメディアにおけるData APIの活用について

37

カスタムフィールド画像の設定コード

my $field = "<form mt:asset-id=\"$asset_id\" class=\"mt-enclosure mt-enclosure-image\" style=\"display: inline;\"><a href=\"$asset->{url}\">$asset->{filename}</a></form>";

my $params = { __method => 'PUT', entry => MT::Util::to_json( { customFields => [ { basename => 'cfmainimage', value => $field, } ], }, ), };

my $content = _request( 'POST', $api_url, $params, $token );

Page 38: ブログメディアにおけるData APIの活用について

38

S

Data API 拡張プラグイン作成

Page 39: ブログメディアにおけるData APIの活用について

39

config.yaml 抜粋

applications: data_api: endpoints: - id: get_asset_information route: /sites/:site_id/assets/:asset_id/info verb: GET version: 1 handler: $DataAPIAssetInfo::DataAPIAssetInfo::EndPoint::Asset::get_asset_info requires_login: 1 - id: set_entry_asset route: /sites/:site_id/assets/:asset_id/set_entry verb: GET version: 1 handler: $DataAPIAssetInfo::DataAPIAssetInfo::EndPoint::Asset::set_entry_asset requires_login: 1

Page 40: ブログメディアにおけるData APIの活用について

40

DataAPIAssetInfo::EndPoint::Asset

sub set_entry_asset { my ($app, $endpoint) = @_;

return $app->error(403) unless $app->can_do('upload'); return $app->error(403) unless $app->param('entry_id');

my ( $blog, $asset ) = context_objects(@_) or return;

run_permission_filter( $app, 'data_api_view_permission_filter', 'asset', $asset->id, obj_promise($blog)) or return;

my $object_asset = MT::ObjectAsset->get_by_key({ asset_id => $asset->id, blog_id => $blog->id, object_ds => 'entry', object_id => $app->param('entry_id'), }); $object_asset->save();

return $asset;}

Page 41: ブログメディアにおけるData APIの活用について

41

S

MT6.1Data API 2.0 対応

Page 42: ブログメディアにおけるData APIの活用について

42

大幅なリファクタリング

共通化できるコードをプラグイン化

2つに分かれていたランキング作成スクリプトを1つに

accessToken が必要なエンドポイントの場合は自動的に token を取得するよう実装

blog_id を複数渡せるように変更 @blog_ids = [ 3, 4 ] : で複数回 Data API にアクセスし、ブログにまたがって結果を

集計できるように拡張

カテゴリーアーカイブのパスを getCategory の archiveLink から取得するように変更

サムネールの作成、エントリーアセットの登録を v2 で拡張された getThumbnail, updateEntry の機能を使うように変更

Page 43: ブログメディアにおけるData APIの活用について

43

複数ブログ対応

ひとまず getBlog と PageviewsForPath のみ対応

blog_id が配列で複数指定された場合 内部オブジェクト W2DataAPI::Blogs,

W2DataAPI::Pageviews に結果を格納し、まとめて返す Blogs の結果は getBlog を配列にしたもの Pageviews の結果は blog_idごとにマージし {items} を

{pageviews} でソートしたもの(ブログを横断してランキングを取得)

Page 44: ブログメディアにおけるData APIの活用について

44

カテゴリーアーカイブパス

v1 ではカテゴリーの情報にパスが含まれていなかったため、 basename からパスを生成する必要があった カテゴリー basename の生成方法によって所作が変わるた

め、コードの一般化が難しい

v2 ではカテゴリーに {archiveLink} が追加された 1つのカテゴリーアーカイブに対して一意の URL が取得で

きるようになった

Page 45: ブログメディアにおけるData APIの活用について

45

サムネールの作成

エンドポイント getThumbnail が追加された(あれ、 v2 のドキュメント getThubmnail になってる?) /v2/sites/:site_id/assets/:asset_id/thumbnail params => width, height, scale, square

独自拡張のエンドポイントをやめ、こちらに書き換え

Page 46: ブログメディアにおけるData APIの活用について

46

エントリーアセットの登録

updateEntry でアセットの紐付けができるようになった

こちらも独自拡張をやめた( APIへのアクセス回数も減った)

my $entry_params = { entry => MT::Util::to_json( { customFields => [ { basename => 'cfmainimage', value => $field, } ], assets => [ { id => $asset_id } ], } ),};

Page 47: ブログメディアにおけるData APIの活用について

47

S

今後

Page 48: ブログメディアにおけるData APIの活用について

48

今後の目標 完全プラグイン化

現在、スクリプトを cron でまわしている スクリプトの配置がハードルが高い MT クラウドでは利用出来ない

完全プラグイン化 print() で HTML タグを出力している部分を MT テンプレー

ト化 cron スクリプトを廃止しタスク化 諸々の設定を管理画面のプラグイン設定から変更可能に