P学習帳

書いておぼえるブログ

Perl入学式 東京第3回、ピザパーティのお題を解く

Perl入学式 東京の第3回にサポーターとして参加させてもらいました。勉強会終了後のピザパーティーで出たお題をやってみたので、そのことについて書いてみます。

やりたいこと

グーグルの検索トレンドデータからキーワードランキングをつくります。ランキングに加えて前日からの推移も含めます。

Googleトレンドのデータは以下のエンドポイントからJSON形式で取れます。

https://trends.google.com/trends/api/dailytrends?geo=JP&ed=yyyymmdd

わかばたいむすさんの記事に詳しくあります。
wakabatimes.com

やってみてわかったこと

・順位の差を求めることができませんでした。前日だとランキング圏外になっていたからです。
Googleトレンドをみると正しいランキングがすぐわかります。 Google Trends

コード

月初の順位前日比を求めるところと結果の出力はさぼっています。

use strict;
use warnings;
use feature 'say';
binmode(STDOUT, ":utf8");
use JSON::XS qw/decode_json/;
use LWP::Simple;
use DateTime;
use DDP;

# Googleトレンドのエンドポイントにいれる日付をyyyymmddの形式でつくる
my $dt = DateTime->now( time_zone => 'Asia/Tokyo' );
my $yyyymmdd = $dt->ymd('/');
my ($y, $m, $d) = split(/\//, $yyyymmdd);
my @days = ();

# 月初から本日までの日にちを配列にいれる(例. 1,2,3...)
if ( $d ne "1" ) {
  my $c = 1;
  my @array;
  $array[$d - 1] = '';
  @days = map { $c++; } @array;
} else {
  @days[0] = "1";
}

# yyyymmdd形式の文字列に変換する
my @dates = ();
for my $day ( @days ) {
  my $dt = DateTime->new(
    time_zone => 'Asia/Tokyo',
    year      => $y,
    month     => $m,
    day       => $day,
  );
  push(@dates, $dt->ymd(''));
}

# 配列に用意した各日付のデータをGoogleに問い合わせる
my $rankings = {};
for my $target_day (@dates) {
  say "day => $target_day";
  my $rank = 1;
  my $content = get("https://trends.google.com/trends/api/dailytrends?geo=JP&ed=$target_day");
  my $json = substr($content, 6); # 1行目のごみを取り除く
  my $data = decode_json($json);

  # 検索ワードのデータまで掘る
  my $article_array_ref = $data->{default}->{trendingSearchesDays}[0]->{trendingSearches};

  # 検索ワードはランク順にならんでいるので、ループしながらランクを付けられる
  for my $article ( @$article_array_ref ) {
    my $query = $article->{title}{query};
    say $query;
    $rankings->{$target_day}{$query}{rank} = $rank;
    $rank++;
  }
}

# ランキングにくわえて前日との順位差を入れるハッシュレフを別につくる
my $trends = $rankings;
my @dates_copy = @dates;
shift @dates_copy;
my @from_second_day_to_later_days = @dates_copy;
my $prev_day = shift @dates;

# 検索ワードごとに前日のランクとの差を求める(ただし、前日だとランク圏外になっていて存在しなかった)
for my $target_day (@from_second_day_to_later_days) {
  for my $query ( keys %{$rankings->{$target_day}} ) {
    my $trend;
    if ( defined($rankings->{$prev_day}{$query}) ) {
      $trend = $rankings->{$prev_day}{$query} - $rankings->{$target_day}{$query};
    } else {
      $trend = "new";
    }
    $trends->{$target_day}{$query}{trend} = $trend;
  }
}

# デバッグプリント
p $trends;

標準出力(一部抜粋)

20190109   {
        NGT            {
            rank    10,
            trend   "new"
        },
        りんご病           {
            rank    15,
            trend   "new"
        },
        アジアカップ         {
            rank    9,
            trend   "new"
        },
        サッカーアジアカップ     {
            rank    7,
            trend   "new"
        },
        サッカー日本代表       {
            rank    5,
            trend   "new"
        },
        トルクメニスタン       {
            rank    3,
            trend   "new"
        },
        バーチャルさんは見ている   {
            rank    14,
            trend   "new"
        },
        ピーチジョン         {
            rank    13,
            trend   "new"
        },
        兼高かおる          {
            rank    6,
            trend   "new"
        },
        友井雄亮           {
            rank    2,
            trend   "new"
        },
        家売る女           {
            rank    8,
            trend   "new"
        },
        尾田栄一郎          {
            rank    4,
            trend   "new"
        },
        山口真帆           {
            rank    1,
            trend   "new"
        },
        志村けん           {
            rank    12,
            trend   "new"
        },
        摂津正            {
            rank    17,
            trend   "new"
        },
        武田玲奈           {
            rank    18,
            trend   "new"
        },
        玉川徹            {
            rank    16,
            trend   "new"
        },
        馬毛島            {
            rank    11,
            trend   "new"
        }
    },
    20190110   {
        はあちゅう             {
            rank    17,
            trend   "new"
        },
        スキャンダル専門弁護士       {
            rank    5,
            trend   "new"
        },
        ディビジョン            {
            rank    18,
            trend   "new"
        },
        ワンピース             {
            rank    4,
            trend   "new"
        },
        京王観光              {
            rank    12,
            trend   "new"
        },
        刑事ゼロ              {
            rank    10,
            trend   "new"
        },
        宇賀なつみ             {
            rank    11,
            trend   "new"
        },
        川谷絵音              {
            rank    13,
            trend   "new"
        },
        '日本 対 トルクメニスタン'   {
            rank    3,
            trend   "new"
        },
        星座                {
            rank    9,
            trend   "new"
        },
        松本人志              {
            rank    15,
            trend   "new"
        },
        森川葵               {
            rank    14,
            trend   "new"
        },
        楠ろあ               {
            rank    7,
            trend   "new"
        },
        盾の勇者の成り上がり        {
            rank    6,
            trend   "new"
        },
        福男                {
            rank    8,
            trend   "new"
        },
        竹下亘               {
            rank    16,
            trend   "new"
        },
        純烈                {
            rank    1,
            trend   -33088
        },
        雨宮萌果              {
            rank    2,
            trend   "new"
        }