はじめに
やること
- Google custom search engine(CSE)で画像を拾ってきて、LINE APIのpushメッセージでその画像を送る
- Google cloud function(GCF)を使ってサーバーレスアーキテクチャで画像を拾ってくるLine botを動かす
この記事のスコープ外のこと
- Google cloud platform(GCP)やCSEの基本的な使い方
- 他にいっぱい記事があるのでGCPのアカウント登録やGCFのチュートリアルはすでに終えている前提として話を進める
Line Messagesing APIを使う
アカウント登録からチャンネル設定まで
基本公式ドキュメントを読んで進めていけば問題ありません。
最終的に今回使う情報は以下の部分です。
pushメッセージを送ってみる
CSEで画像を拾ってきてそれを自分に対して送ってみる。
CSEの使い方はこちらの記事が参考になる。
今回は自分の好きな声優さんの画像を拾ってくることにする。なぜならそちらの方がモチベーションが上がるから(重要)。
- packageインストール
$ mkdir test_project
$ cd test_project
$ npm install @line/bot-sdk --save
$ npm install request --save
$ npm install config --save
- confファイル作成
- channelAccessTokenとchannelSecretは、LINE developersのコンソールから取得できるアクセストークンとChannel secretである
- google APIの方のkeyとcxはAPI keyと検索エンジンIDである
$ mkdir conf
$ vi conf/default.conf
conf/default.conf
{
"lineAPI": {
"channelAccessToken": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"channelSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"googleAPI": {
"key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"cx": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
- 画像をCSEから取得してLINEへメッセージをpushするスクリプト作成
- 今回は画像を送るが、その他にも普通のテキストはもちろん、動画やスタンプ、位置情報等も送れるので公式ドキュメントのメッセージオブジェクトの項目を参照されたし
$ vi search_image.js
search_image.js
'use strict'
const line = require('@line/bot-sdk');
const config = require('config');
const httpClient = require('request')
const lineClient = new line.Client(config.lineAPI);
const url = 'https://www.googleapis.com/customsearch/v1';
const searchWord = '立花理香';
function searchImage(searchWord) {
return new Promise(function(func){
var pageNumber = Math.floor(Math.random() * 10) + 1;
var imageNumber = Math.floor(Math.random() * 10);
var queryStrings = {
q: searchWord,
key: config.googleAPI.key,
cx: config.googleAPI.cx,
searchType: 'image',
start: pageNumber
}
var params = {
url: url,
method: 'GET',
json: true,
qs: queryStrings
}
httpClient.get(params, function(err, res, body) {
if(err){
console.log(err);
}
try {
func(res.body.items[imageNumber].link);
}catch(e){
console.log('Error: ' + e)
}
});
});
};
function returnUrl(imageUrl){
return imageUrl;
};
searchImage(searchWord)
.then(function(imageUrl){
var message = {
"type": "image",
"originalContentUrl": imageUrl,
"previewImageUrl": imageUrl
};
lineClient.pushMessage("<Your Line user ID>", message);
});
これを実行すると……
$ node search_image.js
サーバーレスアーキテクチャでbotとして動かす
上記の声優画像検索スクリプトを少し改修してbotとして動かしてみます。
$ vi index.js
index.js
'use strict';
const line = require('@line/bot-sdk');
const config = require('config');
const httpClient = require('request');
const lineClient = new line.Client(config.lineAPI);
const googleSearch = 'https://www.googleapis.com/customsearch/v1';
function searchImage(searchWord) {
return new Promise(function(func){
var pageNumber = Math.floor(Math.random() * 10) + 1;
var imageNumber = Math.floor(Math.random() * 10);
var queryStrings = {
q: searchWord,
key: config.googleAPI.key,
cx: config.googleAPI.cx,
searchType: 'image',
start: pageNumber
}
var params = {
url: googleSearch,
method: 'GET',
json: true,
qs: queryStrings
}
httpClient.get(params, function(err, res, body) {
if(err){
console.log(err);
return err;
}
try {
func(res.body.items[imageNumber].link)
} catch(e){
console.log('Error: ' + e)
}
});
});
};
function replyWithImage(event, imageUrl){
console.log(imageUrl);
var message = {
"type": "image",
"originalContentUrl": imageUrl,
"previewImageUrl": imageUrl
};
lineClient.replyMessage(event.replyToken, message);
};
function handleEvent(event) {
var searchWord = '立花理香';
searchImage(searchWord)
.then(function(imageUrl){
replyWithImage(event, imageUrl);
});
}
exports.webhook = function webhook(req, res) {
Promise
.all(req.body.events.map(handleEvent))
.then((result) => res.json(result))
.catch((error) => console.error(error));
}
これをGCFにアップロードします。処理に数分かかるかもしれません。
$ gcloud beta functions deploy webhook --trigger-http --source .
Deploying function (may take a while - up to 2 minutes).../
exportsしてgcloudコマンドでdeployした関数がGCF上から呼べるようになります。
完了すると以下のようなメッセージが出力されます。
...
availableMemoryMb: 256
entryPoint: webhook
httpsTrigger:
url: https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/webhook
labels:
deployment-tool: cli-gcloud
...
ここで出てきているurlをLine developersのコンソール画面上からWebhook URLに設定します。
設定が完了したら早速botを呼び出してみましょう。
今回書いたコードではなんでもいいので適当なメッセージを送ると画像を返してくれるはずです。
やったぜ。
課題
- CSEで一度に拾ってこれる画像は100枚が限度、また無料枠は一日100リクエスト(それ以上は有料)
- 画像を大量収集するのには向いてないかな
- 調べるとBing APIを使ってる人の方が多いっぽい?
- 拾ってきた画像がLINE APIのメッセージオブジェクトの制限に引っかかってるぽくて失敗する(ステータスコード400が返ってくる)時がある
- originalContentUrlは最大画像サイズ:1024×1024、最大ファイルサイズ:1MB
- previewImageUrlは最大画像サイズ:240×240、最大ファイルサイズ:1MB