sironekotoroの日記

Perl と Mac の初心者の備忘録

mojolicious::Liteで文字化けるー(解決

やりたいこと

  • 基礎(ドットインストールと「Perl言語プログラミングレッスン」)だけでは眠いので、チャレンジ的にやりたいことをやってみていることにしている。
    • 一時流行った遅延学習法ってやつか
  • 今回はユースケベー氏の「Webサービスの作り方」と「Perlについて語ろう」に書いてあった「Mojolicious::Liteでtuwiiter APIつかってキーワード検索し、ツイートを表示!」ってのをやりたかった。
    • しかし、twitter APIのバージョンが新しくなったためにそのままでは利用できず。
  • 内容的に似ているので、youtube APIで試した。
  • youtube APIに検索ワード決め打ちで入れて、タイトルとURLを返すところまでを実装
  • そのあと、Mojolicious::Liteでそれを表示させる
    • まだ検索ワードの入力機能は入れてない
  • しかしここで問題が。タイトルの日本語が文字化ける
    • 格闘すること4時間、解決せず。
    • Perlの内部文字列がそのまま出ているのかなぁ?
#!/usr/bin/env perl
use strict;
use warnings;

use Mojolicious::Lite;
use WebService::Simple;
use utf8;
use JSON;

get '/' => sub {
    my $self = shift;

    # APIをたたくためにURLを構築する
    my $service = WebService::Simple->new(
        base_url        => 'http://gdata.youtube.com/feeds/api/videos',
        response_parser => 'JSON'
    );

    # データ取得
    my $res = $service->get(
        { q => 'YAPC::ASIA', 'max-results' => '5', alt => 'json' } );
    my $ref = $res->parse_response();

    $self->stash->{youtubes} = $ref->{feed}->{entry};

    $self->render('index');
};

app->start;

__DATA__
% use Mojo::Util;
@@ index.html.ep
% layout 'default';
% title 'Youtube Search Sample';
% for my $entry(@$youtubes){
   <p>
   <%= $entry->{'media$group'}->{'media$description'}->{'$t'} ; %>
   </br>
   <%= $entry->{link}[0]{href} ; %>
   </p>
% }


@@ layouts/default.html.ep
<!DOCTYPE html>
<html lang="ja">
<head>
   <title><%= title %></title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body><%= content %></body>
</html>
  • morboで起動させると・・・

f:id:sironekotoro:20131117100903p:plain

  • とりあえず、きりがないので次に向かうことにする。
  • とか言いつつ、結局気になってしまい、より書籍に書いてあったのに近づけて書いてみた。
    • 具体的にはWebService::Simpleではなく、LWP::UserAgentで書いてみた。
    • 日本語表示きたぁ!
#!/usr/bin/env perl
use strict;
use warnings;

use Mojolicious::Lite;
use URI;
use LWP::UserAgent;
use JSON qw/decode_json/;
use Encode;

get '/' => sub {
    my $self = shift;

    # APIをたたくためにURLを構築する

    my $uri = URI->new("http://gdata.youtube.com/feeds/api/videos");
    $uri->query_form(
        q             => 'YAPC::Asia',
        'max-results' => '5',
        alt           => 'json'
    );

    # データ取得
    my $ua   = LWP::UserAgent->new();
    my $res  = $ua->get($uri);
    my $data = decode_json( $res->content );

    $self->stash->{youtubes} = $data->{feed}->{entry};
    $self->render('index');

};

app->start;

__DATA__

@@ index.html.ep
% layout 'default';
% title 'Youtube Search Sample';

% for my $entry(@$youtubes){
    <p>
    <%= $entry->{'media$group'}->{'media$description'}->{'$t'} ; %>
    <%= $entry->{'media$group'}->{'media$player'}->[0]->{url} ; %>
    </p>
% }


@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head><title><%= title %></title>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
  <body><%= content %></body>
</html>
  • あー、超幸せ
  • でも、なんでWebServide::Simpleのときはダメだったんだろ?
    • 調子に乗って調べるというか、二つのスクリプトの違いをみてみた。
    • レスポンスで帰ってくるときのJSONの処理かなぁ・・・?
  • WebService::Simpleのparse_response()ではなく、JSONモジュールのdecode_jsonつかったらうまくいったー!
    • でも、なんでparse_response()でダメだったんだろ?
#!/usr/bin/env perl

use strict;
use warnings;

use Mojolicious::Lite;
use WebService::Simple;

use JSON qw/decode_json/;

get '/' => sub {
    my $self = shift;

    # APIをたたくためにURLを構築する
    my $service = WebService::Simple->new(
        base_url        => 'http://gdata.youtube.com/feeds/api/videos',
        response_parser => 'JSON'
    );

    # データ取得
    my $res = $service->get(
        { q => 'YAPC::ASIA', 'max-results' => '5', alt => 'json' } );

#    my $ref = $res->parse_response();

    my $data = decode_json($res->content);

    $self->stash->{youtubes} = $data->{feed}->{entry};
    $self->render('index');
};

app->start;

__DATA__
% use Mojo::Util;
@@ index.html.ep
% layout 'default';
% title 'Youtube Search Sample';
% for my $entry(@$youtubes){
    <p>
    <%= $entry->{'media$group'}->{'media$description'}->{'$t'} ; %>
    </br>
    <%= $entry->{link}[0]{href} ; %>
    </p>
% }


@@ layouts/default.html.ep
<!DOCTYPE html>
<html lang="ja">
<head>
    <title><%= title %></title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body><%= content %></body>
</html>