20190829のNode.jsに関する記事は6件です。

ASK SDK Express Adapterを使って、Alexaスキルを作る

Alexaスキルをhttpsホスティングする

ついに公式サポートです。
今だとalexa-hostedスキルやお手軽なものだとBluePrintなんかも登場し、より開発の敷居が下がっていますがAlexaが日本ローンチされた直後は、Lambdaとhttpsホスティングの2種類しか選ぶことが出来ませんでした。2種類の選択肢はあったもののhttpsホスティングする際に求められる要件の検証などが発生するため、事実上はLambdaだけでカスタムスキルを作るということが一般的でした。
そんな少し面倒だったhttpsホスティングスキルが簡単に作れるようになったよというお話です。

Alexaとのやり取りを少しでも速くしたかった

VUIをデザインする上で、最も大切なのは情報過多になりすぎず、人との対話に近づけられるかということです。
人対人で話す時に、問いかけに対して何らかの返答をタイムラグなく相手に返すということを当たり前のように行っています。もちろん、難しい質問に対しては人間も悩むことがあるので、そのような状況に近いレスポンスを作るのであればワンクッション挟んで、「考えてました」とか少し相槌を打つことで違和感を消せるとは思います。
しかし、普通の応答で遅延していたら「人対人の対話」に近づくことは難しいと個人的には考えてます。

そんな状況下で、試行錯誤した結果前職ではhttpsホスティングでAlexaスキルを提供し、Lambda環境よりも1秒レスポンスを速くする施策なんかも挑戦していました。
そんな戦いの記録はこちらからどうぞ。
交通情報系スキルを事例に見る日常生活に溶け込むスキル開発のテクニック

httpsホスティングすると何がいいのか?

Lambdaのコールドスタートによる遅延をなくすことができます。
なので、コールドスタート時に必要になるコンテナの作成時間を削ることが可能になります。
あとは、趣味用のVPSなどでも動かせるのでAWSを使わずとも遊び程度でスキル開発出来るようになるということも1つの利点かなと思います。

コールドスタートってなに?

Lambdaはリクエストが来るたびコンテナを作成し、その上でプログラムを動かし、レスポンスを生成し、戻すという流れを行っています。
作成したコンテナは、一切リクエストがない状況が10分から20分程度続くと終了されます。
定期的にリクエストがあれば、コンテナは生き続けるので、生きているコンテナが再利用されます。再利用時は、コンテナ作成のステップが省略されるので、コールドスタートよりも速い時間で処理を完了します。(再利用する場合のことをウォームスタートと言います。)
このコールドスタート時のコンテナ作成時間は、デプロイパッケージやLambdaに割り当てたメモリ量によって左右されますが、ウォームスタートよりは確実に遅くなってしまいます。アプリのAPIなどであれば、多少のタイムラグも目をつむることも出来ますが、Alexaとの対話として考えた時この余計な時間が邪魔に感じることもあります。

ASK SDK Express Adapter

はい、今回の本題です。
実際にhttpsホスティングできるスキルのコードを見てみましょう!

Install

npm install --save ask-sdk-express-adapter

プロジェクトへのask-sdk-express-adpterのインストールは簡単です。
npmに公開されているask-sdk-express-adapterをインストールするだけでOKです。
これ以外にalexaスキルに必要な、ask-sdk-coreまたは、ask-sdkがプロジェクトに含まれている必要があります。

Sample code

index.js
// ask-sdkの読み込み
const Alexa = require('ask-sdk-core');
// expressの読み込み
const express = require('express');
// ExpressAdapterの読み込み
const { ExpressAdapter } = require('ask-sdk-express-adapter');
// Handlerの判定お助けツールを読み込む
const Util = require('./Utility');

// MARK: 定数群
const PORT_NO = 3000; 
const SKILL_PATH = '/';

// MARK: Handlerの定義

// スキル起動のHandler
const LaunchHandler = {
    canHandle(handlerInput) {
        return Util.checkIntentTypeName(handlerInput, 'LaunchRequest');
    },
    async handle(handlerInput) {
        return handlerInput.responseBuilder
            .speak('ハローワールド') 
            .getResponse();
    }
}

// ヘルプのHandler
const HelpIntentHandler = {
    canHandle(handlerInput) {
        return (Util.checkIntentTypeName(handlerInput, 'IntentRequest', 'AMAZON.HelpIntent'));
    },
    async handle(handlerInput) {
        return handlerInput.responseBuilder
            .speak('使い方を読み上げますよ') 
            .getResponse();
    }
}


// スキル終了のHandler
const SkillEndHandler = {
    canHandle(handlerInput) {
        return (
            Util.checkIntentTypeName(handlerInput, 'IntentRequest', 'AMAZON.CancelIntent')
            || Util.checkIntentTypeName(handlerInput, 'IntentRequest', 'AMAZON.StopIntent')
        );
    },
    handle(handlerInput) {
        return handlerInput.responseBuilder
            .speak('スキルを終了します。') 
            .getResponse();
    }
}

// エラー発生時のHandler
const ErrorHandler = {
    canHandle() {
        return true;
    },
    handle(handlerInput, error) {
        console.log(`Error handled: ${error.message}`);
        return handlerInput.responseBuilder
            .speak('申し訳ありません。内部エラーが発生致しました。再度、スキルを立ち上げ直してください。') 
            .getResponse();
    },
};

// MARK: 初期化関連
const app = express();

const skillBuilder = Alexa.SkillBuilders.custom()
                            .addRequestHandlers(
                                LaunchHandler,
                                HelpIntentHandler,
                                SkillEndHandler
                            )
                            .addErrorHandlers(ErrorHandler)

const skill = skillBuilder.create();
const adapter = new ExpressAdapter(skill, true, true);

app.post(SKILL_PATH, adapter.getRequestHandlers());
app.listen(PORT_NO);

サンプルコードはこちらのリポジトリに置きました。
Github - MasamiYamate/AlexaHttpsHostedSkill

肝の部分

基本的にHandlerの定義などはLambda上で動かすAlexaスキルを作る時と差はありません。
肝となる部分は、下記の部分です。

index.js
const skill = skillBuilder.create();
const adapter = new ExpressAdapter(skill, true, true);

app.post(SKILL_PATH, adapter.getRequestHandlers());
app.listen(PORT_NO);

通常であれば、skillBuilder.lambda();としますが、skillBuilder.create();とします。
skillBuilder.create();にすることで、スキルリクエストのレスポンスをjson形式で取得できるようになります。
ちなみにask-sdk-express-adapterが出る前は、下記のように工夫することでレスポンスのjsonを取得することが出来ました。
過去の例として下記のリポジトリを参考にしてみてください。
Github - MasamiYamate/katana-alexa-https-hosting

レスポンスのjsonを生成するcreate()メソッドを今回新たに公開されたask-sdk-express-adpterを生成するときの引数として渡して、expressの任意のパスをpostで呼び出す時にask-sdk-express-adpterのgetRequestHandlers()を呼び出すようにすれば完了です。

index.js
app.post(SKILL_PATH, adapter.getRequestHandlers());

あとは、expressでListenするポート番号を指定してあげるだけ。
これだけで今まで必要だったリクエストの検証などが一切不要になり、さくらのVPSなどワンコインVPSなどでもAlexaスキルを動かせるようになります。

サーバー側の設定

  • forever...デーモン化ツール
  • nginx...httpsのリクエストを任意のlocalhostに向けるために必要(リバースプロキシ)

上記の2つが必要です。
サーバーにログインしてスキルを立ち上げてもログアウトしてしまえばセッションがなくなりプログラムが止まってしまいます。
なので、ログアウトしていてもスキルが永続的に動くようにforeverを利用してスキルのスクリプトを永続化させます。

また、Alexaへのリクエストはhttpsなので443番のポート番号指定で飛んできます。単純に上記スクリプトのポートを443に指定してあげれば直接Node.jsのサーバーに外部からリクエストを受けることが出来ます。しかし、1024番以下のポートでの実行には管理者権限が必要でセキュリティ的に良くないです。
そんなこともあり、Node.jsでは一般的に3000番などのポートでプログラムを動かし、外部からのリクエストは一度nginxで受け取って、nginxからlocalの3000番に渡すようなことをするのが一般的です。
なので、別途nginxのリバースプロキシの設定をすることをおすすめします。
大体のやり方は、先人の知恵をお借りしたので下記の記事を参照してみてください。
Node.js + Express + forever を構成して nginx から流す

スキルのエンドポイント設定

スクリーンショット 2019-08-29 20.49.03.png
サーバー側の設定が終わったら、Alexa developer consoleのhttpsホスティングを行いたいスキルの画面からエンドポイントの設定を行います。
DefaultではARNの項目にチェックが入っていますので、httpsの項目を選択しエンドポイントを入力します。入力後、証明書の種別を選択して保存すれば作業は完了です。

注意点 - DynamoDBのコールは出来ない

AWS EC2上で動かす場合は、ロールにDynamoDBの権限を付与するだけでhttpsホスティングのスキルスクリプトからDynamoDBにアクセスすることが出来ます。しかし、ワンコインVPSなどの環境からだとDynamoDBをそのまま使うことは出来ません。
以前はAWS EC2上で動かしていたので、まだ未検証ですがおそらくaws-sdkを初期化したりsecretkey等々アクセスに必要な権限などの準備が別途必要になると思います。

また、ask-sdk-express-adpterではこれも未検証ですが、httpsホスティングスキルをAWS EC2上で動かし、実行ロールにDynamoDBの権限を付与していてもaws-sdkにリージョンの指定をしてあげる必要がありました。動き的にexpressで動かすだけのように見えますので、ask-sdk-express-adpterを利用してEC2上でスキルを動かしてかつDynamoDBを利用したい時にうまく動かないことが発生したらまずリージョンの指定がちゃんと出来ているか確認することをおすすめします。
コレに関しては後日追試して確認する予定です。

まとめ

個人的にはalexa-sdk時代からhttpsホスティングできるスキルの開発を行ってきたこともあり公式サポートしてくれたことは非常に嬉しく感じます。
Lambdaでお手軽に実行することに比べると運用を少し気を使わないといけなかったり、スキルのスクリプトのバージョン管理などの手間も発生してしまいます。
ただ、それでもトリッキーなことを試したり、AWSを使わなくてもスキル開発を誰でも簡単にできるようになるパーツとしては良いモノなので、Alexa開発にある程度精通してきた方は挑戦してみると色々楽しいかもしれません!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

kinesisのKPLとKCLに非対応の言語でそれっぽい実装をする

KPL/KCLについて

あえていまさらですが、メリットいろいろあるので余程のノックアウト要件がない限りは

  • KPL(※)を使ってkinesisに書き込み
  • KCL(※)を使ってkinesisから取得する

という形になると思います。

※KPL
https://docs.aws.amazon.com/ja_jp/streams/latest/dev/developing-producers-with-kpl.html
※KCL
https://docs.aws.amazon.com/ja_jp/streams/latest/dev/developing-consumers-with-kcl.html
https://docs.aws.amazon.com/ja_jp/streams/latest/dev/developing-consumers-with-kcl-v2.html

KPL/KCL使いたくない場合もある

KPL/KCLを使うともれなくjavaがついてきますよね
KCLもいろいろな言語の皮をかぶっていますが結局javaっていう感じですし
でもシステム内で そこだけjava みたいな場合は やっぱり使いたくないな。。。 って思いますよね
あとlambdaでkinesisからrecordとってきてささっと保存だけしたいのに 集約されてる。。。 ってなります。

aws-kinesis-aggで集約・集約解除はできる

https://github.com/awslabs/kinesis-aggregation

対応言語
java
go
python
node

集約

ごめんなさい書いてないです。。。
集約を独自に実装する場合はbuffer処理は自分で実装する必要がありそうです。
集約はinterfaceが用意されているので簡単にできそうでした。

集約解除

kplを使って集約したrecordをlambdaで解除してs3に保存します

lambda + node

firehose使えばそれはそれで問題ありません。
でもbucket振り分けたいとか、パスをいろいろいじりたいとかなってくるとロジック書きたくなっちゃうので、そういった用途です。

const aws = require('aws-sdk');
// aws-kinesis-aggはnpm installとだめです
const agg = require('aws-kinesis-agg');

// change time zone
process.env.TZ = 'Asia/Tokyo';

// get aws sdk
const s3 = new aws.S3({ apiVersion: '2006-03-01', region: 'ap-northeast-1' });

exports.handler = async(event, context) => {
    "use strict";
    console.log('Loading function s3 write');

    /* Process the list of records and transform them */
    for (const record of event.Records) {
        /* kinesis aggregate record decode */
        agg.deaggregateSync(record.kinesis, true, (err, userRecords) => {
            if (err) {
                console.error(err);
                return;
            }
            /* record handler */
            console.log(JSON.stringify(userRecords));
            userRecords.forEach(item => {
                let data = Buffer.from(item, 'base64').toString('utf8');
                s3.putObject({
                        Bucket: 'xxxxx',
                        Key: 'xxxxx',
                        Body: data
                    },
                    (err, data) => {
                        if (err) {
                            console.error(`s3 put error ${JSON.stringify(err)}`);
                        }
                    });
                });
        });
    }
    return `Successfully processed ${event.Records.length} records.`;
};

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

goormide から Google Cloud Platform node.js へ NUXT.js SSR をデプロイ

※超初心者が書いた自分への備忘録です。

Google Cloud Platform でプロジェクトを作成する。

goormide にて環境確認

$ node -v
v10.15.3
$ npm -v
6.9.0

● Google Cloud ツール を インストールする。

Google Cloud ツール Ubuntu 用のインストール手順。

$ export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
$ echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
$ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ apt-get -y update && apt-get install -y google-cloud-sdk

$  gcloud -v
Google Cloud SDK 260.0.0
alpha 2019.08.23
beta 2019.08.23
bq 2.0.47
core 2019.08.23
gsutil 4.42
kubectl 2019.08.23

To take a quick anonymous survey, run:
  $ gcloud alpha survey

● SDK の初期化

$ gcloud init
...
You must log in to continue. Would you like to log in (Y/n)?  y
Go to the following link in your browser:
   https://accounts.google.com/o/oauth2/auth?code_challenge=TCp.......reauth

Enter verification code:

上記URLにアクセスして code を取得してペーストする。

Pick cloud project to use:
 [1] clean-mason-xxxxx
 [2] oauth2-xxxxx-xxx
 [3] test-nuxt-xxxxx
 [4] Create a new project
Please enter numeric choice or text value (must exactly match list item): 3

create-nuxt-app でNUXTアプリを作成する。

実行すると対話式でNuxt.jsプロジェクトの作成を行う。

$ cd /workspace
$ npx create-nuxt-app TestNUXTJS

? Project name (gae-node-nuxt-ssr-example) [Enter]
? Project description (My stylish Nuxt.js project) [入力] Nuxt.js Universal Mode on GAE/SE Node.js
? Author name () [入力] beginnnnner
? Choose a package manager (Use arrow keys) [選択] npm
? Choose UI framework (Use arrow keys) [選択] none
? Use a custom server framework [選択] none
? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection) [選択] Axios
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection) [Enter] 
? Choose test framework (Use arrow keys) [Entet] none
? Choose rendering mode (Use arrow keys) [Enter] ❯ Universal (SSR)
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection) [Enter]

...
...
                                      :-:
                                    .==-+:
                                   .==. :+- .-=-
                                  .==.   :==++-+=.
                                 :==.     -**: :+=.
                                :+-      :*+++. .++.
                               :+-      -*= .++: .=+.
                              -+:      =*-   .+*: .=+:
                             -+:     .=*-     .=*-  =+:
                           .==:     .+*:        -*-  -+-
                          .=+:.....:+*-.........:=*=..=*-
                          .-=------=++============++====:

                           Thanks for installing nuxtjs
                  Please consider donating to our open collective

?  Successfully created project TestNUXT

  To get started:

        cd TestNUXT
        npm run dev

  To build & start for production:

        cd TestNUXT
        npm run build
        npm run start

インストールが完了したら以下を実行

$ cd gae-node-nuxt-ssr-example
$ npm run dev

goormide メニュー > プロジェクト > 実行URLとポート > testoop.run.goorm.io 3000 [登録]
指定したURLにブラウザからアクセスする。

Connected refused
上手くいかなかった orz

対応策

nuxt.config.js にポートを指定する。

export default {
  server: {
    port: 8080, // デフォルト: 3000
    host: '0.0.0.0', // デフォルト: localhost
  },

goormide メニュー > プロジェクト > 実行URLとポート > testoop.run.goorm.io 8080 [登録]
指定したURLにブラウザからアクセスする。

Good!

Google App Engine へデプロイする

簡単!GAE/SE Node.jsでNuxt.jsをUniversalモードで動かしてみた
Nuxt.jsプロジェクト直下に以下の内容のapp.yamlファイルを作成します。

runtime: nodejs10

handlers:
  - url: /_nuxt
    static_dir: .nuxt/dist/client
  - url: /.*
    script: auto

env_variables:
  NUXT_HOST: '0.0.0.0'
  NUXT_PORT: '8080'

ビルドしてデプロイする。

$ npm run build
$ gcloud app deploy
...
Do you want to continue (Y/n)?  y

Beginning deployment of service [default]...
Created .gcloudignore file. See `gcloud topic gcloudignore` for details.
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 52 files to Google Cloud Storage               ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...failed.
ERROR: (gcloud.app.deploy) Error Response: [7] Access Not Configured. Cloud Build has not been used in project test-nuxt-xxxx before or it is dis
abled. Enable it by visiting https://console.developers.google.com/apis/api/cloudbuild.googleapis.com/overview?project=test-nuxt-xxxx then retry.
 If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.

Cloud Build API が無効ならを有効にしてからデプロイを実行する。

$ gcloud app deploy
...
Do you want to continue (Y/n)?  y

Beginning deployment of service [default]...
Created .gcloudignore file. See `gcloud topic gcloudignore` for details.
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage                 ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://test-nuxt-xxx.appspot.com]

You can stream logs from the command line by running:
  $ gcloud app logs tail -s default

To view your application in the web browser run:
  $ gcloud app browse

ブラウザで https://test-nuxt-xxx.appspot.com にアクセスする。
キャプチャ.JPG

Google Cloud Platform ダッシュボード

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerを使ってWebサイトをSSL化

目的

DockerとLet's EncryptをつかってWebサイトをSSL化させる。

前提条件

ドメインの取得して名前解決できること。

本構成イメージ

無題.png

順番はあまり関係ないが、⑤は最後に行う。

①exampleexpressイメージ作成

app.js
var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});
packages.json
{
  "name": "exampleexpress",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.14.0"
  }
}
Dockerfile
FROM node:onbuild
EXPOSE 3000
CMD node app.js

以下のコマンドでイメージを作成する。

docker build -t exampleexpress .

②証明書を発行

以下のコマンドを実行

export LETSENCRYPT_EMAIL=<youremailaddress>
export DNSNAME=www.example.com

docker run --rm \
    -p 443:443 -p 80:80 --name letsencrypt \
    -v "/etc/letsencrypt:/etc/letsencrypt" \
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
    quay.io/letsencrypt/letsencrypt:latest \
    certonly -n -m $LETSENCRYPT_EMAIL -d $DNSNAME --standalone --agree-tos

③expressnginxイメージを作成

nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /dev/stdout  main;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  _;
        return 301 https://$host$request_uri;
    }

    server {
        listen              443 ssl;
        #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        server_name         www.example.com;
        ssl_certificate     /etc/letsencrypt/live/www.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;

        location ^~ /.well-known/ {
            root   /usr/share/nginx/html;
            allow all;
        }

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://expresshelloworld:3000;
        }
    }
}
Dockerfile
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf

以下のコマンドを実行

docker build -t expressnginx .

④ネットワーク作成

以下のコマンドを実行

docker network create -d bridge expressnet

⑤Webサーバを動かす

以下のコマンドを実行

docker run -d \
    --name expresshelloworld --net expressnet exampleexpress
docker run -d -p 80:80 -p 443:443 \
    --name expressnginx --net expressnet \
    -v /etc/letsencrypt:/etc/letsencrypt \
    -v /usr/share/nginx/html:/usr/share/nginx/html \
    expressnginx

その他

証明書の更新
以下のコマンドを実行

export LETSENCRYPT_EMAIL=me@example.com
export DNSNAME=www.example.com

docker run --rm --name letsencrypt \
    -v "/etc/letsencrypt:/etc/letsencrypt" \
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
    -v "/usr/share/nginx/html:/usr/share/nginx/html" \
    quay.io/letsencrypt/letsencrypt:latest \
    certonly -n --webroot -w /usr/share/nginx/html -d $DNSNAME --agree-tos
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js上でCUIコマンドを用いたURLスクレイピング

Node.jsを用いたURLスクレイピング

はじめに

Node.jsを用いたスクレイピングは、
記事を漁るとしばしば見受けられます。
Webサーバを立ててリクエスト送るという記事は多いです。
それって、Node.jsの特徴をあまり活かせてないのでは?
と思い立ったためこの記事を書きました。

Node.jsでスクレイピング

JSをサーバサイドでも動作させることができるプラットフォームですが、
JS単体では扱えなかった、CUIコマンドも扱えます。

Webサーバ立てる必要なくない?

Curlコマンド利用してHTTPリクエスト生やして、
HTMLオブジェクトを取得した上でスクレイピングしたほうがよくない?

ということで

Node.js上でCUIコマンドを利用するためには、
child_processモジュール内のexecSync関数を利用します。

余談ですが...
child_processモジュール内のexecSync関数は同期関数
child_processモジュール内のexec関数は非同期関数 なので注意。

CUIExec(argv)関数では引数にURLを指定することで、
該当URLの飛び先にある、HTMLオブジェクトを取得し、
文字列として戻り値に設定します。

index.js
const execSync = require('child_process').execSync;
const CUIExec = (argv) => { // URL
    console.log(argv);
    return execSync("curl " + argv).toString();
}

HTMLオブジェクトを取得したのちに、
正規表現によってhrefタグに紐づけられているURLのみを抽出し、
配列に格納します。

index.js
const urlParserIncludeHTML = (htmlString) => {
    return (htmlString+"").match(/href=\"(.*?)\".*?/gi);
}

if (process.argv[2]) { //コマンドライン引数の取得
    let arrayIncludeURL = [];
    let uriList = [];

    uriList = urlParserIncludeHTML(CUIExec(process.argv[2])).slice();
    console.log(uriList);

    for (let key in uriList) {
        let tmpStr = (uriList[key]+"").replace(/^href="/, "").replace('"', "");
        //任意のファイル拡張子
        if (tmpStr.match(".css") || tmpStr.match(".xml")
            || tmpStr.match(".png") || tmpStr.match(".jpg")
            || tmpStr.match(".svg") || tmpStr.match(".ico")
            || tmpStr.match(".json")) {
            continue;
        } else {
            if (tmpStr.indexOf("http") || tmpStr.indexOf("https")){
                arrayIncludeURL.push(process.argv[2] + tmpStr);
            } else {
                arrayIncludeURL.push(tmpStr);
            }
        }
    }
    console.log(arrayIncludeURL);
}

実行コマンドは以下の通りです。

$ node index.js <URL>

index.jsをchild_processモジュールを利用し、
他のJSファイル上で実行することによって、
他言語との有意差はおいておいても、
JSのみでもソフトウェアの作成が可能です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsからElasticSearch検索

はじめに

曖昧検索、全文検索はElasticSearchのほうがよいと思います。
Node.jsからの利用をする際には、直接ElasticSearchのAPIを呼ぶか、elasticsearchモジュールを利用するかなどの選択肢がありますが、
elasticsearchモジュールを使ったほうが簡単で効率です。

ElasticSearchインストール

npm install elasticsearch

クライアント生成

const elasticsearch = require('elasticsearch');
const client = new elasticsearch.Client({
  host: 'localhost:9200',
  log: 'trace'
});

検索例

const response = await client.search({
  index: 'blogs',
  body: {
    query: {
      "multi_match" : {
        "query":    "Node.js",
        "fields": [ "title", "*_tag" ] 
      }
    }
  }
})


for (const blog of response.hits.hits) {
  console.log('blog:', blog);
}

検索クエリの書き方は下記記事参照:
https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html

AWSのElasticSearchの場合は開発ガイドがあります。
https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/what-is-amazon-elasticsearch-service.html

ElasticSearch新しいJavascriptのクライアントがリリースれました。
https://www.elastic.co/blog/new-elasticsearch-javascript-client-released

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む