【JavaScript】調べたい単語を入力すると Wikipedia の検索結果が返ってくる LINE Bot を作る

概要

GROWI エンジニアの 宮沢 です。今回は、LINE bot を開発することができる、line-bot-sdk-nodejs と JavaScript で Wikipedia の情報を取得できる WIKIJs を組み合わせて、調べたい単語を入力すると、Wikipedia の検索結果が返してくれる LINE bot を作ってみたいと思います。


LINE Messaging API SDK について

今回利用する line-bot-sdk-nodejs は LINE社が提供している Messaging API を JavaScript で簡単に操作できるできるライブラリとなっています。

LINE Messaging API SDK を使ってオウム返しを実装してみる

まずは line-bot-sdk-nodejs を使って、入力した言葉をそのまま返すオウム返しを作ってみます。

例) オウム返し

準備

以下の準備を済ませておきましょう。

  • LINE bot コンソールの登録、Bot の作成、アクセストークンとアクセスシークレットの取得
    -参考: https://developers.line.biz/ja/docs/messaging-api/getting-started/
  • ngrok のインストール
    • トンネリングを用いてローカルサーバーをインターネット上に公開するためのもの
    • Bot をテストする用の簡易サーバー的なやつ
    • Homebrew をお使いの場合は brew install ngrok でインストールできます

オウム返し Bot の実装

適当なプロジェクトを作成して、実装していきます。

#  適当なディレクトリの作成
$ mkdir wikipedia-linebot-sample

# Change Directory
$ cd wikipedia-linebot-sample

# 適当なプロジェクトの作成
$ yarn init

# 必要なライブラリのインストール
$ yarn add @line/bot-sdk dotenv express

.env ファイルをプロジェクトルートに作成して、先ほど取得したアクセストークン、アクセスシークレットを環境変数にセットします。

CHANNEL_ACCESS_TOKEN=<Your Access Token>
CHANNEL_SECRET=<Your Access Secret>

ちょうど line-bot-sdk-nodejs にオウム返しの サンプルコード があったのでこれをそのまま使ってみます。(一部コード、コメントの修正をしています)

const line = require('@line/bot-sdk');
const express = require('express');

require('dotenv').config();

// アクセストークン、アクセスシークレットを入れる
const config = {
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
  channelSecret: process.env.CHANNEL_SECRET,
};

// LINE Bot SDK クライアントの作成
const client = new line.Client(config);

// Express APP の作成
const app = express();

app.get('/', (req, res) => {
  res.send('Hello line bot sample!');
});

// ミドルウェアにウェブフックハンドラを登録
// line.middleware は LINE の Webhook からのアクセスを検証する
// X-Line-Signature ヘッダーのないリクエストは処理されない
app.post('/callback', line.middleware(config), (req, res) => {
  Promise
    .all(req.body.events.map(handleEvent))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err);
      res.status(500).end();
    });
});

// イベントハンドラー
const handleEvent = (event) => {
  if (event.type !== 'message' || event.message.type !== 'text') {
    // イベントタイプがテキストメッセージ以外のものは処理しない
    return Promise.resolve(null);
  }

  // クライアントから入力された文字列をセット
  const echo = { type: 'text', text: event.message.text };

  // リプライ API を用いてクライアントから入力さレた文字列をそのまま返信
  return client.replyMessage(event.replyToken, echo);
}

// listen on port
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`listening on ${port}`);
});

プロジェクトルートに index.js を作成、以上のコードを記述します。

現在の /wikipedia-linebot-sample の中身は以下のようになっていると思います。

.
├── index.js
├── node_modules
├── package.json
└── yarn.lock

次にサーバーの起動、ngrok を使ってインターネット上に公開します

# サーバー起動
$ node index.js

# 3000 番で起動しているサーバーをインターネット上に公開
$ ngrok http 3000

ngrok コマンドが無事成功すると接続状況などが書かれた画面が表示され、公開された URL( https://5d8d-113-41-130-33.ngrok.io みたいなやつ) が取得できると思います。この URL を LINE bot コンソールで作成した Bot の Webhook URL に設定します。

これでオウム返しの Bot が完成です。LINE で作成した Bot を友達追加して遊んでみましょう。

WIKIJs を使って JavaScript で Wikipedia を検索してみる

何はともあれライブラリのインストール(/wikipedia-linebot-sample)

$ yarn add wikijs

単語を入れるとその概要を出力するコードを書いてみます。

const wiki = require('wikijs');

// 日本語の検索結果が返ってくる API
const apiUrl = 'https://ja.wikipedia.org/w/api.php';

const getWikipediaSummary = async(searchText) => {
  try {
    // 引数で調べたい単語を取得、Wikipedia で検索する
    const page = await wiki.default({apiUrl}).page(searchText);

    // Wikipedia の検索結果の概要を取得し返却
    const pageInfo = await page.summary();
    return pageInfo
  }
  catch (err) {
    console.log('err');
  }
};

const main = async() => {
  const wikipediaSummary = await getWikipediaSummary('チェンソーマン');
  console.log(wikipediaSummary);
};

main();

プロジェクトルートに wikipedia.js を作成、以上のコードを記述して実行してみます。

出力結果

『チェンソーマン』(Chainsaw Man)は、藤本タツキによる日本の漫画作品である。『週刊少年ジャンプ』(集英社)にて第1部「公安編」が2019年1号から2021年2号まで連載され、第2部「学園編」は『少年ジャンプ+』(同社)にて2022年7月13日より連載中。2022年7月時点でコミックス計11巻の累計部数は1300万部を突破している。

数行のコードでここまでやってくれるのは便利ですね〜。

  🤜  組み合わせる 🤛

では最後に、Wikipedia の検索結果が返ってくる LINE bot に改造してみます。先ほど作成した wikipedia.jsindex.js を書き換えます。

wikipedia.js

const wiki = require('wikijs');

const apiUrl = 'https://ja.wikipedia.org/w/api.php';

const getWikipediaSummary = async(searchText) => {
  try {
    const page = await wiki.default({apiUrl}).page(searchText);
    const pageInfo = await page.summary();
    return pageInfo
  }
  catch (err) {
    console.log('err');
  }
};

module.exports = getWikipediaSummary;

index.js

const line = require('@line/bot-sdk');
const express = require('express');

require('dotenv').config();

const getWikipediaSummary = require('./wikipedia');

const config = {
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
  channelSecret: process.env.CHANNEL_SECRET,
};

const client = new line.Client(config);

const app = express();

app.get('/', (req, res) => {
  res.send('Hello line bot sample!');
});

app.post('/callback', line.middleware(config), (req, res) => {
  Promise
    .all(req.body.events.map(handleEvent))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err);
      res.status(500).end();
    });
});

const handleEvent = async(event) => {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  // クライアントから入力された文字列から Wikipedia の概要を取得しクライアントに返却
  const wikipediaSummary = await getWikipediaSummary(event.message.text);
  const message = { type: 'text', text: wikipediaSummary != null ? wikipediaSummary : '検索結果が見つかりませんでした' };
  return client.replyMessage(event.replyToken, message);
}

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`listening on ${port}`);
});

ひとまずこれで、Wikipedia の検索結果が返ってくる LINE Bot の完成です。LINE で調べたい単語を入力して遊んでみてください。

今回は JavaScript で作成しましたが、筆者が学生自体に Python で作ったものが Heroku で動いているので友達登録をして遊んでみてください。