ニコニコ動画に投稿された動画に広告を設定することができる「ニコニ広告」ですが、いちいち毎日無料で回せる福引を確認しに行くことが億劫だと思ったことはありませんか?
というわけで、ニコニ広告のページで通信コンソールを見ながらAPIを見つけてきたのでご紹介です。

注意

この記事では、公開されていないAPIを使用しています。そのため、予告なくAPIが使用できなくなったり、アカウントが停止される可能性は大いにあります。使用する際は自己責任で。何か問題が発生しても執筆者は責任を一切取りません。
また、不正にキャンペーンに参加する行為は禁止となっています。この記事で解説する内容はあくまで開催されているキャンペーンを取得するだけですので問題はないと思いますが、応用的に自動で福引を回すような動作をさせるのはやめましょう。また、APIに連続して接続し、ニコニコ側に負荷をかける行為も絶対にやめましょう。

目次

API EndPoint

早速、APIのエンドポイントを記載しておきます。ログインが必要ですので後述する方法などを用いてログインしてください。
https://api.nicoad.nicovideo.jp/v1/conductors?conductorFrameId=6

実践

今回は、以下のような流れで通知するシステムを構築します。実際に私が運用しているシステムです。
言語はPHPを使用しますが、難しいシステムではないのである程度の知識があれば移植も簡単にできると思います。

  1. ニコニコにログインします。
  2. APIを使用して現在実施されている福引のリストを取得します。
  3. APIで取得したデータから、URLを取り出し接続・取得後、スクレイピングで必要な情報を取り出します。
  4. Discordを通じて通知します。

1. ニコニコにログインします。

今回は私が自作したniconicoクラスを使用して、ログイン作業を行います。
以下のようなプログラムを書き、ログイン作業を行いましょう。

require_once("niconico.class.php"); // niconicoクラスをロード
try{
    $niconico = new niconico("MAIL_ADDRESS", "PASSWORD"); // ログイン
}catch(Exception $e){
    exit("Error: " . $e->getMessage()); // ログインに失敗したら終了
}

2. APIを使用して現在実施されている福引のリストを取得します。

上記で書いたAPIのエンドポイントを使用して、福引のリストを取得しましょう。

$conductors = $niconico->getJSON("https://api.nicoad.nicovideo.jp/v1/conductors?conductorFrameId=6"); // JSON形式でAPIを叩く
if($conductors["meta"]["status"] != 200){ // ステータスが200でなければ
    exit("取得に失敗しました。"); // 処理を終了
}

取得してきたデータは以下のような感じです。

{
    "meta": {
        "status": 200
    },
    "data": {
        "conductors": [
            {
                "bannerImageUrl": "https://secure-dcdn.cdn.nimg.jp/nicoad/res/conductors/free_beginner.png",
                "text": "null",
                "url": "http://blog.nicovideo.jp/niconews/69156.html"
            },
            {
                "bannerImageUrl": "https://secure-dcdn.cdn.nimg.jp/nicoad/res/conductors/free_jackpot_chance_1805.png",
                "text": "null",
                "url": "http://blog.nicovideo.jp/niconews/74511.html"
            },
            {
                "bannerImageUrl": "https://secure-dcdn.cdn.nimg.jp/nicoad/res/conductors/nicoad_month_end_201805.png",
                "text": "null",
                "url": "http://blog.nicovideo.jp/niconews/74510.html"
            }
        ]
    }
}

ちなみに、このAPIを見つけたのはニコニ広告のトップページのバー(画像赤枠)が表示されるタイミングでこのAPIを通信していたのがネットワークコンソールから見えたのでこれだと判断しました。

3. APIで取得したデータから、URLを取り出し接続・取得後、スクレイピングで必要な情報を取り出します。

配列分繰り返す中で、福引のニコニコインフォページのURLが["data"]["conductors"][*]["url"]で取得できるので、取得しタイトルなどを接続・取得しましょう。

ただし、その前に今回は最終的にDiscordに通知するため、私が自作したDiscordEmbedクラスをロードして使用します。

require_once("DiscordEmbed.class.php"); // DiscordEmbedクラスをロード
$embed = new DiscordEmbed(); // 新しく作成
$embed->setTitle("ニコニ広告"); // タイトルを設定
$embed->setUrl("https://nicoad.nicovideo.jp/"); // URLを設定

function getInnerHtml($node){
    $children = $node->childNodes;
    $html = '';
    foreach($children as $child){
        $html .= $node->ownerDocument->saveHTML($child);
    }
    return $html;
}
function br2nl($string){
    return preg_replace('/<br[[:space:]]*\/?[[:space:]]*>/i', "\n", $string);
}

foreach($conductors["data"]["conductors"] as $i => $conductor){ // 福引のイベント数分繰り返す(①)
    $url = $conductor["url"];
    $data = file_get_contents($url); // URLから接続します。
    preg_match("/<title>([^<]++)<\/title>/i", $data, $m); // タイトルをスクレイピング
    $title = $m[1]; // タイトルがなかった場合の処置をしていませんが、本来はisset($m[1])やcount($m)などでチェックすべきでしょう。
    $title = str_replace("|ニコニコインフォ", "", $title); // 無駄な「|ニコニコインフォ」というテキストを消してしまいます。

    $dom = new DOMDocument(); // PHP5あたりからあるDOMDocumentを使用します。
    @$dom->loadHTML($html); // HTMLをロード。何かHTML構文が間違ってるだけでエラー吐くので@を使用して抑制します。
    $xpath = new DOMXPath($dom); // スクレイピングできるようにします。
    $content = $xpath->query('//*[@class="article-body"]')->item(0); // classがarticle-bodyという要素を取得します。
    $content = getInnerHtml($content); // 要素のHTMLを取得します。
    $content = br2nl($content); // brタグを改行に変換します。
    $content = strip_tags($content); // HTMLタグを削除します。

    preg_match("/ニコニ広告(.+)実施します。/", $content, $enforcement); // おおざっぱな実施内容を取得
    $enforcement = $enforcement[0]; // タイトル同様本来は存在しなかった場合の処置をすべき

    preg_match("/キャンペーン内容([\s\S]+?) /", $content, $campaign); // 詳しいキャンペーン内容を取得
    $campaign = $campaign[1]; // タイトル同様本来は存在しなかった場合の処置をすべき

    $embed->addFields("[" . $i . "] " . $title, $enforcement . "\n" . $campaign . $url, false); // 今まで取得してきたデータから通知文章を構成しフィールドに追加
} // ①に戻る

4. Discordを通じて通知します。

以下のようにして、Discordを使用して通知します。
メッセージ送信には、以下の記事にある「DiscordMessageSend」を使用して送信します。

Discordでのメッセージ送信について

$embed->setDescription("本日使用できるニコニ広告は " . ($i + 1) . " 個あります。");
DiscordMessageSend("CHANNELID", "", $embed->Export());

結果


画像のような形で通知されます。crontab等で毎日動作させるといいでしょう。なお、00:00に実行すると前日の情報を取得してくるようなので、ちょっと遅らせて取得したほうが良いと思います。

今回は以上です。