- 投稿日:2019-10-08T23:53:37+09:00
twitモジュール使ってキーワード指定したつぶやきをリアルタイムで抽出する
はじめに
twitモジュールが便利すぎたので記念に投稿。
参考書籍
JS+Node.jsによるWebクローラー/ネットエージェント開発テクニック
実行環境
・Windows10
・VirtualBox
・Vagrant 2.2.5
・Node.js v6.17.1
・Twitter Developers 登録済みモジュールのインストール
ソースコード置き場に移動して以下のコマンド実行。
成功すると、同ディレクトリ上にnode_modulesディレクトリができあがる[vagrant@localhost 02-twitter]$ npm install twit --no-bin-links /vagrant_data/src/ch06/02-twitter mqw twit@2.2.11 mqw request@2.88.0 mqw http-signature@1.2.0 mqw sshpk@1.16.1 tqq asn1@0.2.4 tqq bcrypt-pbkdf@1.0.2 tqq dashdash@1.14.1 tqq ecc-jsbn@0.1.2 tqq getpass@0.1.7 tqq jsbn@0.1.1 tqq safer-buffer@2.1.2 mqq tweetnacl@0.14.5 npm WARN enoent ENOENT: no such file or directory, open '/vagrant_data/src/ch06/02-twitter/package.json' npm WARN 02-twitter No description npm WARN 02-twitter No repository field. npm WARN 02-twitter No README data npm WARN 02-twitter No license field. [vagrant@localhost 02-twitter]$ ls node_modules twi-app-test.jsTwitter APIキーを確認する
- Twitter Developersにログインする
- 画面右上あたりにある[Get Started]クリック
- 画面真ん中あたり[Create An App]クリック
- 画面の指示に従ってアプリ登録に必要な事項を記入&登録
- 登録されたら4種のキーが発行されるのでメモとる ↓↓みたいなやつがもらえる
キーは使われると困るので伏字(***)にしてますConsumer API keys ******************* (API key) @@@@@@@@@@@@@@@@@@@ (API secret key) Regenerate Access token & access token secret ???????????????????? (Access token) !!!!!!!!!!!!!!!!!!!! (Access token secret)プログラムの作成
ごく短いプログラムを作る↓↓
// Twitterを使ったテスト var Twit = require('twit'); // 以下正しいキーを設定 var T = Twit({ consumer_key:'*******************', consumer_secret:'@@@@@@@@@@@@@@@@@@@', access_token:'????????????????????', access_token_secret:'!!!!!!!!!!!!!!!!!!!!' }); // Javascriptに関するつぶやきを表示する var stream = T.stream('statuses/filter', {track: 'Kaggle'} ); // つぶやきがあったときに呼ばれるイベントを設定 stream.on('tweet', function (tw) { var text = tw.text; var user_name = tw.user.name; console.log(user_name + "> " + text); });うごかしてみる
実行結果は↓↓。 ※試しの雰囲気を見てほしいだけなので名前とかは伏字にしときます
起動してぼんやり眺めるだけでもなんとなく楽しいかもしれない。[vagrant@localhost 02-twitter]$ node twi-app-test.js ????> RT @MLBear2: 幸いにも上位に入れたので初めてSolutionを投稿しました。特殊なコンペ(?)だったので他コンペにそのまま流用で きるノウハウは多くないかもですが、adversarial validationをあえて完全無視したとか、他のsolutionが書いてないよ… ????> @radekosmulski @jeremyphoward @kaggle @RSNA @threader_app ????> Curiosamente, las mayores dificultades que encuentro son la manipulacion de datos previa entrada a la red, y que el… https://t.co/jHmvM68xdu
- 投稿日:2019-10-08T23:22:35+09:00
npmでのモジュールのインストールしたときに失敗した時の対処法
はじめに
Windows上でVirtualboxを使って開発環境を作ったとき
共有フォルダ設定を使ったパス上でnpm install...してるとエラーがでた。
これの対処法をメモ参考
https://qiita.com/sansaisoba/items/0fd5c77c9fbbfe61a629
によると、
Windows環境(と、Windowsホストの共有フォルダにVagrantなどからnpmを実行した場合)では、
npm installで以下のエラーが発生することがある。
…だそうです。自分の環境は、Windows+Virtualbox+Vagrantなのでまんま同じシチュエーションだった。。。
やること
npm install [モジュール名] --no-bin-links
という感じで末尾にオプションを作る実際は↓↓な感じ。twitモジュールをインストールするときはこうする。
$ npm install twit --no-bin-links
- 投稿日:2019-10-08T22:39:14+09:00
node.jsをインストールしてurl指定のファイルをダウンロードする
前提条件
CentOS6.5
node.js v0.12.4 ← これをインストールする手順
- node.jsのインストール
- sudoコマンド実行時のパスを普段のユーザのパスと同等にしてやる
- プログラム作成
- 実行
1.node.jsのインストール
CentOSにsshログインして以下のコマンド実行。
実は一度インストールした後にコマンドの再確認的な意味合いでやったので
already installedとか出てるけど、そこは気にしないことにする[vagrant@localhost ~]$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.3/install.sh | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 7149 100 7149 0 0 10538 0 --:--:-- --:--:-- --:--:-- 25084 => Downloading nvm from git to '/home/vagrant/.nvm' => fatal: destination path '/home/vagrant/.nvm' already exists and is not an empty directory. [vagrant@localhost ~]$ nvm install v0.12.4 v0.12.4 is already installed. Now using node v0.12.4 (npm v2.10.1) [vagrant@localhost ~]$ nvm alias default v0.12.4 default -> v0.12.4 [vagrant@localhost ~]$ node -v v0.12.4 [vagrant@localhost ~]$2. sudoコマンド実行時のパスを普段のユーザのパスと同等にしてやる
nvmを利用してNode.jsをインストールした場合、sudoコマンドを利用した時に
npmやnodeコマンドが利用できないためvisudoを使って利用できるようにする$sudo visudoテキストファイルの編集画面に切り替わるので以下のように編集する
Defaults env_reset ↓↓ Defaults !env_reset # Defaults env_keep += "HOME" ↓↓ Defaults env_keep += "HOME" Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin ↓↓ # Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin3. プログラム作成
以下のプログラムを作成する。ミニサイズなので全文おいとく。
拡張子は"js"/home/vagrant/src/ch02/01-download/download-node.js// urlにあるファイルを savepath にダウンロードする // ダウンロード元URLの指定 var url = "http://kujirahand.com" //保存先のパスを指定 var savepath = "test.html" // 利用モジュールの取り込み var http = require('http'); // HTTPのモジュール var fs = require('fs'); // ファイル関連モジュール // 出力先を指定 var outfile = fs.createWriteStream(savepath); // 非同期でURLからファイルをダウンロード http.get(url, function(res) { res.pipe(outfile); res.on('end', function (){ outfile.close(); console.log("ok"); }); });4.実行する
jsのファイルのある場所まで移動してnodeコマンド実行。
プログラムのつくりの問題だけど"ok"の出力があれば無事成功。[vagrant@localhost 01-download]$ pwd
/home/vagrant/src/ch02/01-download
[vagrant@localhost 01-download]$ node download-node.js
ok結果確認
同フォルダにtest.htmlができているので内容チェックして確認
[vagrant@localhost 01-download]$ ls download-node.js test.html [vagrant@localhost 01-download]$ cat test.html <html><body><a href="https://kujirahand.com/wiki/index.php">kujirahand.com</a><br></body></html>[vagrant@localhost 01-download]$おわりに
インストールしてしまえば結構さらっと終わった
javascriptでこんなに作りこんだことないから
ちょっと慌てるけど徐々に慣れていけばいいかなと。~おしまい~
- 投稿日:2019-10-08T18:30:07+09:00
SendGrid,Heroku,Gmailを使って無料で特定のメールだけをSlackチャンネルに転送する
はじめに
今までZappierとgmailを使って特定のメールをSlackチャンネルに転送をしていました。
Zappierは設定がとっても楽チンで非常に良かったんですが、
無料プランだと1月当たり100通しか転送できず別の方法を考えることにしました。Slackも無料プランのためEmailアドオンが使うことができず、
それでも無料でチャンネルにメール転送したいと思い実際にやってみました。
(個人アカウントへの転送はSlackが無料プランでもメールアドレス発行出来るので出来ます)本記事での目標
Gmailで件名に【TEST】が入っているメールを受け取ったら、
Slackのテストチャンネルに、送信元、件名、本文が自動で投稿されるようにする。目次
今回使用するもの、サービス
- SendGrid(Parse Webhook) : メール受け取り、Herokuに用意したAPIにPOSTする
- Heroku(Node, Express) : 受け取ったメールをパース、整形し、Slackのincomig-webhookにPOSTする
- freenom : 無料ドメイン取得、Parse Webhookを利用するため必要
- gmail : メールをフィルタリングし、Slackに送りたいメールだけ転送する
- Slack : Incoming Webhookでメール内容受け取り、任意チャンネルに投稿する
概要図
手順
※各サービスのアカウント作成とfreenomでのドメイン取得方法に関しては割愛します。
※今回用に事前にfreenomで以下ドメインを取得しました。
SendGrid : Domain Authentication設定
SendGridでメールを受け取るためのドメインの設定をします。
SendGrid管理画面からSender Authenticationをクリック
Authentication Your Domainをクリック
Domain You Send Fromに取得したドメインを入力しNextをクリック
ここまで来たら以下画像のように3件のCNAMEレコードが表示されるのでfreenomで追加します。
SendGridでVerifyをクリックし3件全てVerifiedになったらOKです。
※注意※ドメイン取得から使用できるようになるまで最大3日程度かかる場合があります。
Slack : Incoming Webhookの設定
チャンネルにIncoming Webhookアプリを追加、Webhook URLを取得します。
プログラム作成
※nodeは10.13.0を使用しています。
適当なディレクトリを作成し、必要モジュールをインストール
- express : Webアプリケーションフレームワーク
- multer : メールがmultipart/form-data形式で飛んでくるため使用
- axios : Incoming WebhookへPOSTするため使用
- html-to-text : HTML形式メール対応のため使用
$ mkdir test $ cd test $ npm -y init $ npm i --save express multer axios html-to-text $ touch index.jsプログラム本体:index.js
index.jsconst multer = require("multer"); const axios = require("axios"); const htmlToText = require("html-to-text"); const app = require("express")(); app.set("port", process.env.PORT || 3000); const webhookUrl = "https://hooks.slack.com/services/*********/*********/**********************"; // 各自webhookUrlを設定ください app.post("/", multer().any(), (req, res) => { (async () => { try { await axios.post(webhookUrl, { text: ` From : ${req.body.from} Subject : ${req.body.subject} Body : ${req.body.text || htmlToText.fromString(req.body.html)} ` }); res.status(200).send({ success: true }); } catch (e) { console.error(e); res.status(500).send({ success: false, error: e }); } })(); }); app.listen(app.get("port"), () => { console.log(`Express server listening on port ${app.get("port")}`); });Herokuデプロイ
※Heroku CLIをインストールしておいてください(https://devcenter.heroku.com/articles/heroku-cli)
Heroku上で空のアプリを用意しておいてください。
今回はアプリ名takahirosato-test-appで作成しました。login
$ heroku login
さっき作ったtestディレクトリ下で以下実行
$ git init $ heroku git:remote -a takahirosato-test-appnode_modulesをignore
$ echo "/node_modules/" > .gitignoreProcfile作成
$ echo "web: node index.js" > Procfilecommit & push
$ git add . $ git commit -am "make it better" $ git push heroku masterエラーがでなければオッケイ☆
SendGrid : Inbound Parse設定
SendGrid管理画面からInbound Parseをクリック
ここまでで、とりあえずem8892.takahirosato.tkに送られるメールは全てSlackのテストチャンネルに転送されるようになりました。
Gmail : フィルタリング & 転送
Gmailで受け取ったメールから特定のメールだけを転送するよう設定します。
Gmailの設定からメール転送とPOP/IMAPをクリック
転送先アドレスを追加をクリックしアドレス入力
※@の前は何でも良いです
確認コードがSlackに届きます
確認コードを入力して転送先アドレス設定完了
次のアドレスに転送するにチェックを入れ、先程登録したアドレスを設定しフィルタを作成をクリック
ここまでで、このGmailアカウントに送られたメールの内、件名に【TEST】が含まれるものだけがSlackのテストチャンネルに送られるようになりました。
めでたい
終わりに
実際に職場のメールとSlackで2ヶ月ほど使用しましたが、Herokuの1月当たりの無料使用可能時間(550時間)の内、数十時間程度しか使用してなかったので、Zappierと比べてかなり余裕ありそうです。
また、今回はSlackへの転送でしたが、SendGridとHerokuの組み合わせはかなり色々できそうだなと思いました。
添付ファイルも受け取れるので、添付Excelの中身を見てSlackに報告なんてこともやってます。
GASにAPI作ってスプレッドシートに書き込むみたいなのも楽しそう。
- 投稿日:2019-10-08T17:17:10+09:00
【Node.js】指定したディレクトリ以下のファイル群をコピーする
指定したディレクトリ以下のファイルをコピーする
指定したでディレクトリ配下のファイルをコピーし、
コピー先にファイルがない場合にのみコピーを行う処理を行うモジュールが
必要であったため自作したものを備忘録としてあげておきます。また、取得する関数の紹介ばかりで、
同期処理など含めておらず実用的でない記事が多かったため、
この記事を書きました。記事を読むために
- node npm の環境構築が可能
- ES6 が理解できる
- async await (同期処理/非同期処理)を理解できる
コード
まずfsモジュールのreaddirSync()を用いて該当ディレクトリ配下にある、
ディレクトリ、またはファイル名を取得する処理を書いていきます。
readdir():非同期処理
readdirSync(): 同期処理
これらを用いることで引数に渡したディレクトリ配下の
ディレクトリ名やファイル名を取得することができます。関数の処理が非同期であると戻り値が担保されないため、
async awaitとthen()を利用します。import fs from 'fs' const getFileNameList = async (originFilePath) => { // fileListがreturnされるまで待機 return await fs.readdirSync(originFilePath, (err, fileList) => { if (err) throw err return fileList }) }次にfsモジュールのcopyFileSync()を利用し、
取得したファイル群を指定したディレクトリ配下にコピーしていきます。import fs from 'fs' import path from 'path' const copyFilesToDir = (originDir, copyDir) => { getFileNameList(path.resolve(originDir) + '/') .then(list => { // 処理完了後に処理を実行し戻り値を担保 const fileNameList = list.slice() fileNameList.forEach((fileName) => { try { // fs.constants.COPYFILE_EXCLをオプションに設定 // コピー先に同名ファイルが存在した場合に例外を出す // 指定しない場合は上書き fs.copyFileSync( path.resolve(copyDir + fileName), path.resolve(originDir + fileName), fs.constants.COPYFILE_EXCL ) console.log('copied:' + path.resolve(originDir + fileName)) } catch(err) { // ファイルがすでに存在する場合 EEXIST // ディレクトリが存在しない場合 ENOENT console.log(err) } }) }) }汎用的にしたつもりですので、
カスタムなどして利用してみてもいいかもしれません。
- 投稿日:2019-10-08T16:14:55+09:00
YarnやNPMでscriptsを実行する際に、コマンド名がわからずにpackage.jsonを確認する人へ
package.jsonに定義しているstartやtestは覚えていますが、自分で新たに定義したscriptsの名称はしばらく実行していないと忘れてしまいます。
yarn run
ornpm run
と実行するだけでscriptsの一覧が見れます。
yarnに至っては実行後にコマンドの入力を求めてくれます。# yarnで実行した場合 $ yarn run - build react-scripts-ts build - eject react-scripts-ts eject - start react-scripts-ts start question Which command would you like to run?:
yarn run
をyarn run xxx
として使うコマンドとして覚えていると、気づかない機能でした
- 投稿日:2019-10-08T15:22:23+09:00
Node.jsのコンソールから入力サンプル
はじめに
Node.jsにおいてコンソール(ターミナル)から値を入力するサンプルを掲載します。
例題として、基礎代謝量の計算例を示します。
1日の必要なカロリーを計算して、ダイエットにお役立てください。前提
- OS : Windows7以上
- PoweShellのターミナルで実行
- VSCodeでコード編集
- node.js環境構築済み
基礎代謝量とは
生命を維持するために必要なエネルギー量を基礎代謝量(BMR)といいます。
ハリス・ベネディクト方程式(改良版)を使って基礎代謝量を計算します。
男性: 13.397×体重kg+4.799×身長cm−5.677×年齢+88.362
女性: 9.247×体重kg+3.098×身長cm−4.33×年齢+447.593bmr.js
/** * 基礎代謝量(BMR)計算 * @param {int} sex - 性別 男=0 女=1 * @param {float} weight - 体重 * @param {float} hight - 身長 * @param {int} age - 年齢 */ const bmr = (sex,weight,hight,age) => { if (sex == 0 ) { var kcal = 13.397 * weight + 4.799 * hight - 5.677 * age + 88.362; } else { var kcal = 9.247 * weight + 3.098 * hight - 4.33 * age + 447.593; } return kcal; } /** * コンソール出力メッセージ * @param {int} index - メッセージインデックス */ const outmsg = (index) => { var msg = ''; switch (index) { case 0: msg = "性別" break; case 1: msg = "体重 Kg" break; case 2: msg = "身長 cm" break; case 3: msg = "年齢" break; default: msg = "???" break; } return msg; } var count = 0; // メッセージカウンター var msg = ''; // メッセージ var buf = []; // 一時バッファ var standard_input = process.stdin; standard_input.setEncoding('utf-8'); console.log("性別 男性:0 女性:1"); standard_input.on('data', function (data) { var msg = outmsg(count); console.log(msg + " = "+ data); buf.push(data); count++; if (count == 4 ) { console.log("基礎代謝量 Kcal = " + bmr(buf[0],buf[1],buf[2],buf[3])); process.exit(); } var msg = outmsg(count); console.log(msg); });説明
- 関数 bmr 性別,体重,身長,年齢を引数として、基礎代謝量を返却します。
- 関数 outmsg インデックスを引数として、対応するメッセージを返却します。
- 標準入力はprocess.stdinでハンドルします。ハンドルはstamdard_inputで定義。
- 標準入力のonイベントで入力をトラップします。
- onイベントで入力した結果のdataをカウント順にバッファリングします。
- カウンタが4になったら、bmr関数へバッファリングした値を引数として呼びだします。
- bmr関数の返却値、つまり基礎代謝量を出力します。
実行方法
node bmr.js実行結果
性別 男性:0 女性:1 0 性別 = 0 体重 Kg 69 体重 Kg = 69 身長 cm 168 身長 cm = 168 年齢 36 年齢 = 36 基礎代謝量 Kcal = 1614.615まとめ
htmlの画面を作るまでもない、単純入力をコンソールから入力する場合、
process.stdinはonイベントでprocess.exitするまでコンソールからの入力を取得できます。
このやりかたをマスターすれば、色々応用できます。
ネットで検索すると、コンソール入力の色々な方法を見いだせます。
今回のやり方も参考にしてください。
- 投稿日:2019-10-08T15:10:03+09:00
WEBフロントエンドはじめにシンプルに覚える事 (NodeJS)
関連技術とポイント
とりあえずGitHub
なんでもOSSな時代、gitで人のソースをとにかく読んで書き方を参考にするべし。
シンプルどころで言えば、こちらを参考としてみるのも有りかもしれないUnderscore日本語リファレンス
データを扱う参考になるし、いたってシンプルな書き方をしている。フレームワーク
なくても動かせるようだが、基本使うもの
- Express
シンプルなよく使われるフレームワーク
他にも有名どころとして、「Meteor」や「Sails」などが挙げられる。基本や関連(フロントサイド多め)
非同期処理
ちょっと理解が難しいですが、ある関数が返す結果が欲しいんだけど、書き方によっては結果が返ってくるのを待たずに次の処理に移る状態。
多分DB連携とか、データをどこかから取得してくる時にぶつかる壁だろう。asyncとかpromiseとかコールバックとかネストとか書き方がそれぞれあるけど、最初は読みやすいコードや、似ているコードのやつとかを書いてみると、理解を深めて行けると思う。
※ 書き方が多いだけで正直そんなに難しい話しじゃないJSフレームワーク
JQuery,React,Angular,Vue等々あるが、
JQueryと後の3つはかなりの別物である。 基本的にJQueryは簡単に慣れると思うし使いやすいと感じる。 後の3つは概念を理解するのが少し大変であるが、使用できた場合の恩恵が強いと思う。(高速,再利用,コーディング量)
vueなら比較的簡単に覚えられる気がするので、入り口に向いているかもしれない。コーディング
JSの事
まずECMAScript2015のこと。 ES5とES6について理解が必要。
簡単に言えば古いブラウザとかは新しい書き方すると動かないよって話し。※念の為頭の片隅にでも、できたらbabelとトランスパイルとかも、、
基本的にはES6で書いていればいいと思う。
○ざっと簡単な所
- 変数宣言:let
とvar
とconst
- アロー関数:=>
関数定義をシンプルに
- テンプレート文字列? バッククォート ※これ便利const URL = 'https://hogehoge' const HOGA_URL = `${URL}/hogahoga/`コーディングのこと
書くことが慣れてきたら、eslintで書き方を統一させてみる。
デザイン
cssフレームワークを導入することにより、ある程度のデザインをおまかせしよう。
BootstrapやSemanticUIなど有名どころでアイコンやボタンなどは簡単にそれらしく出来る。パッケージマネージャ(yarn・npm)
パッケージマネージャーは、npmだけでは無い。(だよね)
yarnの方が早いよって事だけ知っていれば大丈夫。ビルドやwebpack babelのこと
古いブラウザで使ってもらうためトランスパイルや、早く表示するために圧縮したりをbabelやwebpack使ってやるよって話し。※なんとなく単語だけ知っていればいいかなって感じです
CDN(コンテンツ・デリバリ・ネットワーク)
ソースとか画像とかを、見てる人の近くのCDNサーバから取ってこよって技術。
JQueryとかBootstrapとかこんな感じにHTMLに記述すれば、読み込めるよって事。
※ちなみにCDN市場最大の会社は アカマイ(akamai)<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Bootstrapの基本テンプレート</title> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <h1>Bootstrapの基本テンプレート</h1> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> </body> </html>サーバーレス(クラウド)
もはやNodeJS関係ないが、マイクロサービスやRestAPIの事は抑えておく必要がある。
簡単な説明だと、フロントに静的webサイト等を設け、バックエンドにサーバーレス構成を挟むような形を取る。そうする事でセキュリティ・コスト・運用を最適化する事が出来るようだ。
- 静的webサイトホスティング・・・AWS/S3, gitHub, Firebase
- サーバーレス・・・AWS/lambda, IBM/Functions
※このサーバーレスにNode,jsがよく使われたりする。テスト
jestやmochaを使ってテストをしよう。
どうやらjestがいいらしい。。基本や便利npmモジュール
request
どこかのRestAPI叩きたい時に使うasync
非同期処理をシンプル化moment
時間や日付系body-parser
リクエストのbodyをパースする(POSTでJSONとかを送りたい場合に使った気がする)Underscore
関数や配列、オブジェクトを扱う際に発生する処理をシンプル化dotenv
環境変数 .envとかhelmet
アプリケーション保護passport
認証ライブラリforever
デーモン化fs
ファイル読み込みとか出力とかデータベース接続系
mysql,mongodb...etcツール
VSコード(Visual Studio Code )
協力コードエディタ、Gitやdockerなど連携が容易でかなり軽い。 最強だと思っている。GitLab
無料だし。 静的Webサイトをホスト出来る。さいごに
覚える事が多い世界だが、複雑で面白いと思う。
クラウドが出てきて、確実に昔の世代より簡単にモノが作れるようになっていると思う。
そんな時代に何か新しいサービスを発信したいですね。
- 投稿日:2019-10-08T14:55:33+09:00
シンプルNodeJS理解 実践
はじめに
備忘録および、これからNodeJS等を体系的にシンプルに理解したい方向けに簡単に書いてみようと思う。
NodeJSとは
サーバーで動くJavaScript環境のこと。
言語がフロントエンド・バックエンド同じような書き方で作成することができ、学習コストが低い。特徴 メリット
- スクリプト言語であること(インタプリタ型)・・・コンパイルがいらない=機械語に変換する必要がないので簡単(めんどくさくない)
- 軽量かんたん・・・軽量で簡単に使えます。。
- リアルタイム処理に向いている(ゲームとかチャットボットとか向いてるって)
npmとNode起動の所
パッケージ管理npmについて
ここから簡単にNodeの使用について説明していこうと思う。
初めての人はインストールして、実践しながら見てもらえればと思う。 ※推奨版を推奨
NodeJSインストール
node -v
・・・バージョン確認npmとは
まずNodeをインストールをするとnpmも一緒にインストールされている事がわかる。
npm -v
・・・確認
これは先人たちの技術の結晶であるパッケージ、npmはそのマネージャーであり、コマンド一発でその恩恵を受けることができる。
- 簡単にnpmでできること
パッケージインストール テスト実行 アプリ起動 バージョン管理Nodeでは
package.json
ファイルで内容を管理されている。理解するために以下を実施
1: 準備// 必要なモジュールをインストール(gオプションはグローバル(PC)つけないとローカル(ディレクトリ)へって意味) npm install -g express npm install -g express-generator2: 空フォルダでプロジェクト作成
express sampleappsampleappのフォルダが作成され、実行に必要なファイルが作られている。
. ├── app.js //実行ファイル ├── bin │ └── www ├── package.json //※※※これ※※※ ├── public //フロントサイド側 JS等 │ ├── images │ ├── javascripts │ └── stylesheets │ └── style.css ├── routes //サーバーサイド側 NodeJS │ ├── index.js │ └── users.js └── views //サーバーサイド側HTMLみたいな ├── error.jade ├── index.jade └── layout.jade
package.jsonの中身を簡単にご説明
scriptsに書かれている事がnpmで実行できること、ここでは
npm start
コマンドで実行される内容が書いてある。
scriptsにはtestとかlintとかビルド系とかを書いたり、環境変数をつけたり等、色々実行コマンドを書くことが出来る。dependenciesではモジュールの名前を書く
何のパッケージなのかは省略。基本パッケージ名 npm
のように調べればすぐ見つかる。
横の数字はパッケージのバージョン。
※たまにバージョンで起動出来ないこととかある(Nodeのバージョンとか、一緒に開発しててとか)package.json{ "name": "sampleapp", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "cookie-parser": "~1.4.3", "debug": "~2.6.9", "express": "~4.16.0", "http-errors": "~1.6.2", "jade": "~1.11.0", "morgan": "~1.9.0" } }Node起動
sampleapp起動
モジュールをインストールする。
ディレクトリにある、package.jsonを見て必要なモジュールをnode_modules
フォルダを作成して入れてくれる。npm install
完了したらアプリ起動してみよう
npm start //またはstartに記載されていた node ./bin/www起動した状態で以下のURLにアクセスする。
http://localhost:3000/
ここまでのステップで難しく思えた人はいないだろう。
ここから、応用に移っていきたいと思う。Node起動をもう少しシンプルに掘り下げる
単体起動とnpm起動
hello.jsfunction Hello(hi) { console.log(hi) } function main(){ Hello('Hello, World') } main()上で作成したsampleappのフォルダで問題ないので、このhello.jsを作って単体で実行する。
※かなり適当なシンプルさだが、こちらで理解していただけると嬉しい。実行
node hello.js実行するとコンソールにHello, Worldが表示されただろうか。
このように単体でも簡単に起動やテスト等の確認をすることが出来る。 たまに簡単なツールを作りたい場合はこのように切り離して使用するような事もする。次はこのHello, Worldを表示するだけのやつをnpmで実行したいと思う。
statの部分を以下に変更してnpm start
で実行する。package.json{ "name": "sampleapp", "version": "0.0.0", "private": true, "scripts": { "start": "node hello" }, "dependencies": { "cookie-parser": "~1.4.3", "debug": "~2.6.9", "express": "~4.16.0", "http-errors": "~1.6.2", "jade": "~1.11.0", "morgan": "~1.9.0" } }ここまでで、起動部分のNodeとnpmの関連性が把握出来てくれれば嬉しい。
npmモジュールを追加とhtml+Node
- indexファイル作成
- sampleappのフォルダに下の超シンプルindex.jsを作成する。
※基本app.jsかindex.jsかserver.jsがメインのファイルだと思って貰えればよいです。index.js// 使うモジュールの宣言 var express = require('express'); var app = express(); var cfenv = require('cfenv'); // 静的なフォルダの場所を宣言 app.use(express.static(__dirname + '/public')); // このアプリの情報をget var appEnv = cfenv.getAppEnv(); // URL(get)の処理、この場合上で宣言したフォルダのindex.htmlをレンダリングしている app.get('/', function(req, res, next) { // res.send('ページが表示されました!'); こんな送り方もある。 res.render('index', {}); }); // ポートとか勝手に選んで開始してくれる // start server on the specified port and binding host app.listen(appEnv.port, '0.0.0.0', function() { // print a message when the server starts listening console.log("server starting on " + appEnv.url); });
- public直下に単純なHTMLのindex.htmlを作成
index.html<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="/css/index.css"> </head> <body> <h1>hello world</h1> </body> </html>
- 足りないモジュールを追加
新しく使うcfenv
を追加するnpm install cfenv
package.json
にcfenvが追加されただろうか。 されていない場合は-sオプションをつけて追加しよう。
※ なかったら起動の時に怒られて分かるので問題はあまり無いかもしれないが、
node index
かpackage.jsonのstart値を変更してnpm start
今度はコンソールにURLが表示されると思うので
server starting on http://localhost:****
、そのURLへ接続してhello world画面の確認。まとめ
難しい話を無しにすると、ここまで出来れば後はカスタマイズしていくだけとなる。
フロント HTML+Javascript+CSS
バック Node.js(get,post等のリクエストを)
- 投稿日:2019-10-08T14:24:04+09:00
AmazonAPIGatewayのLambdaAuthorizer(Node.js)でJWTを検証する(LambdaをServerlessFrameworkでデプロイする)
はじめに
AWSでAPIを構築する際、必ずといっていいほど登場するのがAmazonAPIGatewayですよね。
APIGatewayの認証ってどうされてますか?
- 別に必要ないからしてない
- APIKeyを使っている
- CognitoをAuthorizerにしてトークンの検証をする
- LambdaAuthorizerでトークンの検証をする
など色々なパターンがあると思います。今回は最後に書いた「LambdaAuthorizerでトークンの検証をする」について説明して、その構成をServerlessFrameworkでデプロイするところまでを書いていきます。
登場人物
JSON Web Token (JWT)
JSONをベースとしたトークン。
「ヘッダー / ペイロード / 署名」といった3つのセクションから構成されていて、署名はヘッダーとペイロードのハッシュされた組み合わせです。
hogehoge.foofoofoo.barbarbarbar
のような文字列です。ServerlessFramework
Serverlessなアーキテクチャを構築するためのフレームワーク。AWSだけじゃなくAzureやGCPなど他のクラウドサービスでも利用することができる。
詳しくは 公式ページ で確認してみてください。構成
Lambda Authorizer
JWTの検証をLambda内で行っていきます。
今回はNode.js(TypeScript)での例を書いています。authorizer.tsimport { Handler, Context, Callback, CustomAuthorizerEvent } from "aws-lambda" import * as jsonwebtoken from "jsonwebtoken" import jwkToPem from "jwk-to-pem" import jwk from "./jwk" const pem = jwkToPem(jwk as any) export const handler: Handler = async ( event: CustomAuthorizerEvent, _context: Context, callback: Callback ): Promise<any> => { console.log(JSON.stringify(event)) jsonwebtoken.verify( event.authorizationToken, pem, { algorithms: ["RS256"] }, (err: jsonwebtoken.VerifyErrors, decodedToken: object | string) => { if (err) { callback(null, { principalId: 1, policyDocument: { Version: "2012-10-17", Statement: [ { Action: "execute-api:Invoke", Effect: "Deny", Resource: event.methodArn } ] }, context: { messagge: "Custom Error Message" } }) } else { console.log(decodedToken) callback(null, { principalId: 1, policyDocument: { Version: "2012-10-17", Statement: [ { Action: "execute-api:Invoke", Effect: "Allow", Resource: event.methodArn } ] }, context: { messagge: "Custom Allow Message" } }) } } ) }解説
JWT検証で使うモジュールをインストール
$ yarn add jsonwebtoken jwk-to-pem $ yarn add -D @types/jsonwebtoken @types/jwk-to-pem
jsonwebtoken
がJWTトークンの検証をするライブラリです。
jwt-to-pem
はJWTトークンを検証するための JSON Web Key (JWK) をpem形式に変換するライブラリです。JWT検証
jsonwebtoken
のverify
というメソッドを使って検証をします。jsonwebtoken.verify( event.authorizationToken, // requestHeader内のToken pem, // JWKから生成したpem { algorithms: ["RS256"] }, (err: jsonwebtoken.VerifyErrors, decodedToken: object | string) => {} )( Cognitoを使っている場合のJWK取得 )
Cognitoが発行したJWTの検証に使うJWKは
https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
から取得する事ができます。
そのJSONを何かしらの方法でimportしてください。今回の例はTSファイルにしてimportしています。
また上記のURLからJWKを取得すると2つKeyが入っていますが、最初の一つを利用すればいいです。jwk.tsexport default { alg: "RS256", e: "XXXX", kid: "xxxxxxxxxxxxxx", kty: "RSA", n: "xxxxxxxxxxxxxx", use: "sig" }検証後の処理
CallbackでAPIGatewayにレスポンスを返して行きます。
Statement内のEffectがAllow
かDeny
かでその後の処理を判断させます。// 成功時 callback(null, { principalId: 1, policyDocument: { Version: "2012-10-17", Statement: [ { Action: "execute-api:Invoke", Effect: "Allow", Resource: event.methodArn } ] }, context: { messagge: "Custom Allow Message" } }) // 失敗時 callback(null, { principalId: 1, policyDocument: { Version: "2012-10-17", Statement: [ { Action: "execute-api:Invoke", Effect: "Deny", Resource: event.methodArn } ] }, context: { messagge: "Custom Error Message" } })ServerlessFrameworkでデプロイする
プロジェクト作成
LambdaのソースコードをTypeScriptで書いているので、TypeScript用のテンプレートを使ってプロジェクトを作成します。
$ npx -p serverless sls create -t aws-nodejs-typescript -p example-serverless-tsserverless.yml
AuthorizerをつけたいAPIGatewayをイベントとするfunctionの中に
authorizer
を追加していきます。
name
はAuthorizerとなるLambdaです。同じyml内で定義している場合はこのname
で参照することができます。外部でデプロイされているLambdaをAuthorizerにしたい場合は、arn
に対してそのLambdaのARNを指定します。identitySource
はTokenをどこを参照すれば習得できるのかという設定です。この場合はリクエストヘッダー内のAuthorization
を参照するようになっています。type
はAuthorizerとなるLambdaのeventに渡される値の設定です。単純にTokenを取得したいだけならtoken
がおすすめです。リクエストの内容をすべて取得したい場合はrequest
を指定します。authorizer: name: authorizer identitySource: method.request.header.Authorization type: token全体としてはこんな感じになります。
serverless.ymlservice: name: lambdda-node-ts plugins: - serverless-webpack provider: name: aws runtime: nodejs10.x region: ap-northeast-1 functions: authorizer: handler: authorizer.handler index: handler: index.handler events: - http: method: get path: hello cors: true authorizer: name: authorizer identitySource: method.request.header.Authorization type: tokenあとは
sls deploy
でデプロイすれば作業は完了です。さいごに
今回はLambdaAuthorizerを紹介しました。
トークンの検証にLamdbaを使うことで、トークンの検証以外にもAPIに対するリクエストのログを取ることができたり、怪しいリクエストが来た場合にメール送信などカスタマイズすることができます。
Lambdaを挟むことでかなりできることの幅が広がります!
ではまた!!
- 投稿日:2019-10-08T13:05:26+09:00
Nodeでスプシデータをcsv→jsonに変換して、条件に合う要素をリスト化する
スプシの大規模データを整理するときに楽になったので備忘録として残します。
この記事で扱うデータはフィクションです。実在の人物や団体などとは関係ありません。
※この記事のダミーデータはこちらからお借りしています。
→テストデータ・ジェネレータ
この記事の目標 : 住所が大阪の人をリストアップしてテキストデータに書き出す!使用環境
OS: macOS
Node: v12.2.0
npm: 6.9.0パッケージのインストール
Nodeとnpmの環境設定は省略しています。
まずはターミナルから適当なプロジェクトフォルダに必要なパッケージをインストールします。$npm init -y $npm i -D fs csvtojson js-beautifycsvtojsonがコンバータ
csv -> json の変換
変換スクリプトを書く
csvjson_converter.jslet fs = require('fs'); let csv = require('csvtojson'); let beautify = require('js-beautify').js; let csvFile = './checksheet.csv'; csv().fromFile(csvFile).then((jsonData)=>{ fs.writeFile('checksheet.json', beautify(JSON.stringify(jsonData),{}), function(err) { if (err) console.log('error', err); }); });スプシからダウンロードした[checksheet.csv]を[checksheet.json]に変換して
beautifyでインデントを追加して書き出す命令を記述。$ node csvjson_converter.jsターミナルからスクリプトを実行
こんな感じのjsonが書き出されました。必要な要素をリスト化してテキストデータに保存する。
条件を絞って、[.txt]データに書き出します。
checkitem.jslet fs = require('fs'); // check item let json = JSON.parse(fs.readFileSync("checksheet.json")); let targetItem = []; json.forEach(function(value,index){ if(value.住所.match(/大阪/)){ // console.log(value.url); targetItem.push(value.名前+" : "+value.住所+"\n"); } }); fs.writeFile('大阪の人.txt',targetItem,function(err){ let texts = fs.readFileSync('大阪の人.txt','utf-8'); console.log(texts); fs.writeFile('大阪の人.txt',texts.replace(/\,/g,""),function(err){}); });先ほど書き出した[checksheet.json]を読み込んで、[住所]の項目が[大阪]を含む値を判定。
条件に当てはまったデータを[大阪の人.txt]に書き出し。$ node checkitem.jsターミナルからスクリプトを実行
正しく出て来た。
この記事で扱うデータはフィクションです。実在の人物や団体などとは関係ありませ
条件式の使い方次第で色々絞り込めます。
↓生年月日から20代を絞り込みの場合checkitem.js//if(value.住所.match(/大阪/)){ if(1998 >= value.生年月日.slice(0,4) && 1989 <= value.生年月日.slice(0,4)){おわりに
スプシのフィルタ機能でカバーできない様な、痒いところに手が届いた気がしました。
スプシ1行目に空のデータがあると、自動で"field番号":[{値},{..}]
が当て込まれるので注意です。うまく書き換えて、ejsを使ったHTML書き出しにも使えそうです。
出典
- 投稿日:2019-10-08T10:07:29+09:00
Node-redでスマートハウス-Gravioで戸締り確認[3/3]
はじめに
夏になって、窓を開ける機会も多くなってきました。ただ、家を出るときに戸締りを確認するのは面倒ですよね。
また、出かけてから「あれ?窓ちゃんと閉めたか記憶がない!?」ってことありませんか?
今回は、家の窓がちゃんと閉まっているかをお知らせしてくれる玄関ランプを制作してみたいと思います。やりたいこと
最終的にやりたいのは、窓に取り付けた窓センサーの情報をDBに格納しておき、玄関に人が来た時にLEDライトを赤or青に光らせるというものです。
1.窓センサーで窓の鍵の開閉情報を取得
2.開閉情報をmongoDBに格納
3.人感センサーで玄関に人が来たことを検知
4.LEDライトを赤or青に光らせて戸締り状況をお知らせ
実現に向けた連載
やりたいことを実現するために、以下のように少しずつに記事を書いていきます。
1回目:窓センサーの設定
2回目:人感センサーの設定
3回目:LEDライトの設定 ←この記事3回目:LEDライトの設定
第3回目では、LEDライトを設定し、全ての窓が閉まっていたら「青色」、どこかの窓が開いていたら「赤色」にLEDライトが光るように設定します。また、ライトが点きっぱなしだと困るので、1分で消灯するようにします。
1.スマートリモコンの設定
今回使用するLEDライトは、IFTTTからの制御ができるものなのですが、IFTTT連携の不具合があるようで、現在は使えません。そこで今回は、すでに家に設置済みのsRemo-Rを使用してLEDライトを制御します。sRemo-Rの設定は以下の通りですが、詳細は割愛します。
1.LEDライト付属のリモコンから赤外線信号をsRemo-Rに学習させる
-点灯ボタン(No.61に割り当て)
-消灯ボタン(No.62に割り当て)
-赤色ボタン(No.63に割り当て)
-青色ボタン(No.64に割り当て)
2.sRemo-Rのマクロ機能で以下を設定
-点灯→赤色に変更(No.71に割り当て)
-点灯→青色に変更(No.72に割り当て)2.sRemo-R APIアクセストークンの取得
sRemo-RはWeb APIに対応していて、WebAPIを叩くことでリモコン操作が可能です。node-redから操作するためにAPIアクセストークンを取得します。ここも詳細は割愛します。
1.sRemo-Rのユーザサイトにログイン
2.API用アクセストークン管理のメニューを選択
3.APIサーバ名とAPIアクセストークンを取得3.Node-redの設定
ここからはNode-redを使って、sRemo-RのWebAPIを叩く設定を行っていきます。
①Switchノードの設定
前回設定した「編集」ノードの右側に、Switchノードを追加し、以下のように設定します。
②execノードの設定1
次に、execノードを追加し、ライトを青色に点灯するように設定します。この部分が今回のキーポイントです。・uapi1.sremo.netの部分:上で取得したAPIサーバ名
・AAAAAAAAAAAの部分:sRemo識別子(どのsRemo-Rから送信するか)
・0-71の部分:「0-」は固定でその後に、上で設定したリモコン番号。今回は「71」。
・Bearer XXXXXXXXの部分:「Bearer 」は固定で、その後に上で取得したAPIアクセストークンコマンドcurl https://uapi1.sremo.net/user_api/AAAAAAAAAAA/send_sig?sig=0-71 -H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"③Switchノードの設定2
同様に、execノードをもう一つ追加し、ライトを「赤色」に点灯するように設定します。今回は「72」を設定します。コマンドcurl https://uapi1.sremo.net/user_api/AAAAAAAAAAA/send_sig?sig=0-72 -H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"④execノードの設定
次に、Delayノードを追加し、待ち時間を1分に設定します。⑤execノードの設定3
execノードをもう一つ追加し、ライトを「消灯」するように設定します。今回は「62」を設定します。コマンドcurl https://uapi1.sremo.net/user_api/AAAAAAAAAAA/send_sig?sig=0-62 -H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"⑥ノードの接続
追加したノードを以下のように接続し、LEDライトを赤or青に点灯させ、1分待った後に消灯するように設定します。
⑦Deploy
右上の「Deploy」ボタンを押し、設定したフローをデブロイしましょう。⑧テスト
これで設定は完了です。人感センサーの前に立つと、窓の状態に合わせてLEDライトが青色もしくは赤色に点灯しましたか?おわりに
今回は玄関に設置するLEDライトの設定を行い、sRemo-rを用いてLEDライトを青色もしくは赤色に点灯することをやってみました。本来は、IFTTT連携でスマートにやりたかったので、IFTTT連携の不具合が解消されたら、記事も更新したいと思います。
連載記事
1回目:窓センサーの設定
2回目:人感センサーの設定
3回目:LEDライトの設定 ←この記事