Skip to content

Instantly share code, notes, and snippets.

@sfpgmr
Last active October 23, 2016 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfpgmr/f1de9a051c2a61d23aa5 to your computer and use it in GitHub Desktop.
Save sfpgmr/f1de9a051c2a61d23aa5 to your computer and use it in GitHub Desktop.
Youtube API Test 0001

##このサンプルについて

nodeからYoutube Data APIを呼んでd3とectを使用しサムネイルHTMLファイルを静的に生成する。

生成した静的ページは以下のリンクを参照。

http://www.sfpgmr.net/test/Youtube/0001/

##使用しているライブラリ

  • q.js
  • d3.js
  • ect
  • Bootstrap
<!DOCTYPE html>
<html vocab="http://schema.org">
<head>
<title><%= @title %></title>
<meta charset="utf-8" />
<meta name="description" content="<%- @description %>" />
<meta name="keywords" content="<%- @keywords %>" />
<meta name="author" content="<%- @author %>" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<% content 'header-script' %>
<script type="text/javascript">
if (!location.href.match(/localhost/)) {
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-15457703-9']);
_gaq.push(['_trackPageview']);
(function () {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
}
</script>
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top " role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<div><a class="navbar-brand" href="#" property="headLine" id="headLine" style="margin-top:auto;margin-bottom:auto;"><%-@header %></a></div>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse">
<% content 'nav-content' %>
</div>
</div>
</nav>
<article id="article" typeof="Article">
<header class="container"><h2><%-@title %></h2></header>
<% content 'article' %>
</article>
<footer id="footer" class="navbar navbar-default navbar-fixed-bottom">
<div class="container">
<div class="row">
<div class="col-xs-3" property="creator" id="creator">
<div typeof="person" id="creatorPerson">
<span property="name" id="creatorName">By <a href="http://www.enoie.net/">S.F.</a></span>
</div>
</div>
<div class="col-xs-3 text-center"><% content 'footer-content' %></div>
<div class="col-xs-6 text-right"><small><time id="date" property="dc:date" datetime="<%-@datetime %>"><%= @datestr %></time></small></div>
</div>
</div>
</footer>
<% content 'etc-content' %>
</body>
</html>
<% extend 'template_base.html' %>
<% block 'article' : %>
<div property="articleBody" id="articleBody" class="container">
<%- @articleBody %>
</div>
<% end %>
<% block 'header-script' : %>
<link rel="stylesheet" href="css/main.min.css" />
<% end %>
<% block 'nav-content' : %>
<p class="navbar-text navbar-right"><a href="/" class="navbar-link"><span class="glyphicon glyphicon-home"></span>ホーム</a></p>
<% end %>
<% block 'footer-content' : %>
<% end %>
<% block 'etc-content' : %>
<% end %>
//
// Youtube API Sample
//
//The MIT License(MIT)
//Copyright(c) 2014 Satoshi Fujiwara
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files(the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject tothe following conditions:
//
// The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
var util = require('util');
var https = require('https');
var fs = require('fs');
var d3 = require('d3');
var q = require('q');
var ect = require('ect');
var readFile = q.nfbind(fs.readFile);
var writeFile = q.nfbind(fs.writeFile);
q.all([readFile('../apikey.json', 'utf-8'), readFile('../config.json', 'utf-8')])
.spread(function (keys, config) {
keys = JSON.parse(keys);
config = JSON.parse(config);
var json = q.nfbind(d3.json);
var result = [];
var defer = q.defer();
function getData(pageToken) {
var pt = '';
if (pageToken) {
pt = '&pageToken=' + pageToken;
}
callYoutubeAPI('https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCgwM0kBBsDRMZDhhWuTNR-g&order=date&maxResults=50' + pt + '&key=' + keys.youtube)
.then(function (d) {
result = result.concat(dt.items);
if (dt.nextPageToken) {
getData(dt.nextPageToken);
} else {
defer.resolve();
}
});
}
getData();
defer.promise.then(function () {
var thumb = d3.select('body').selectAll('div')
.data(result)
.enter()
.append('div')
.classed({ 'col-xs-12': true, 'col-md-4': true, 'col-lg-3': true })
.append('div')
.classed('thumbnail', true)
.style('height', '400px')
.style('overflow', 'auto');
console.log(result.length);
thumb.append('a')
.attr('href', function (d) {
var contentsUrl = 'https://www.youtube.com/';
if (d.id.kind == 'youtube#playlist') {
contentsUrl += 'playlist?list=' + d.id.playlistId;
} else if (d.id.kind == 'youtube#video') {
contentsUrl += 'watch?v=' + d.id.videoId;
} else if (d.id.kind == 'youtube#channel') {
contentsUrl += 'channel/' + d.id.channelId;
}
return contentsUrl;
})
.attr('target', '_blank')
.append('img')
.attr('src', function (d) { return d.snippet.thumbnails.high.url; })
.attr('alt', function (d) { return d.snippet.title; });
var cap = thumb
.append('div')
.classed('caption', true);
cap.append('h4').text(function (d) { return d.snippet.title; });
cap.append('p').text(function (d) { return d.snippet.description; });
var renderer = ect({ root : './' });
var now = new Date();
var data = {
header : 'Youtube Test',
title : 'Youtube Test 0001 - 動画をサムネイルする',
description: 'Youtube Test 0001 - 動画をサムネイルする',
keywords : 'Youtube,d3.js',
author: 'sfpgmr',
articleBody: d3.select('body').html(),
datetime:now.toISOString(),
datestr:now.toISOString()
};
//console.log(d3.select('body').html());
return writeFile(config.contentRoot + '/test/Youtube/0001' + '/index.html', renderer.render('template_yt0001.html', data), 'utf-8');
});
return defer.promise;
})
.catch(function (e) {
console.log(e);
})
.done(function () {
console.log('処理終了');
});
function callYoutubeAPI(url) {
var d = q.defer();
https.get(url, function (res) {
var body = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function (res) {
// ret = JSON.parse(body);
d.resolve(body);
body = void (0);
});
}).on('error', function (e) {
console.log(e);
d.reject(e);
});
return d.promise;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment