LoginSignup
15
27

More than 1 year has passed since last update.

GASでお手軽なAPIを作ってJSで叩いてみる

Last updated at Posted at 2021-07-20

備忘録ついでに書いておきます。

無料で簡単にJSONを返してくれるAPIを作りたかったので、GAS(Google Apps Script)を利用してみました。全体的な流れとしては、weblioの英和辞書で、検索した単語の意味一覧をJSONで返すAPIを作り、それをローカルのJSから取得します。ライブラリは使いたくなかったのでaxiosなどは使用していません。

GASでスクレイピング

まずはGASへアクセスして新規プロジェクトを立ち上げましょう。そして、スクレイピングするために「Parser」というライブラリを導入します。「ライブラリの追加」から、スクリプトIDに「1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw」で検索して追加することができます。

次に、スクレイピングする対象であるweblioの構造を見ていきます。
まず、URLに注目するとhttps://ejje.weblio.jp/content/(単語名)で、調べたい単語の意味一覧にに飛べるようです。
また、ページのソースを見ると、<div class=level0>のタグの中に意味が格納されていることが分かりました。
構造が大体わかったので、実際にスクレイピングしてみます。

function doGet(e) {
  // スクレイピング対象のurlを定義
  let url = `https://ejje.weblio.jp/content/${e.parameter.word}`;

  // HTMLの取得
  let html = UrlFetchApp.fetch(url).getContentText();
  // 要素の抽出
  let data = Parser.data(html)
  .from('<div class=level0>')
  .to('</div>')
  .iterate();
}

${e.parameter}でGETリクエスト時のパラメータを受け渡すことができます。渡す際はURLの末尾に?word=(検索したい単語)を追加してアクセスします。
html要素の抽出はUrlFetchApp.fetch(url).getContentText();で行い、同一のタグが複数ある場合はParser.data(html).from(タグ名開始).to(タグ名終了).iterate()で配列にまとめることができます。

スクレイピングしたデータをJSONにして返す

前項のdataではまだ、不要なタグや配列の形式のままになっているので、正規表現で不要部分を削除する作業と、データを後で扱いやすいようにするためにオブジェクト形式にしてキーを追加する作業を行いたいと思います。
まずは正規表現を使ってタグを消し、リストにまとめていきます。

const dataList = []
for (const content in data) {
  dataList.push(data[content].replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,''));
}

次に、dataListをオブジェクトにして一つずつキーを追加していきます。

const newDataList = dataList.map((word, key) => ({key, word}));

最後に、JSON形式に変換して返します。

const json_data = JSON.stringify(newDataList);
return ContentService.createTextOutput(json_data).setMimeType(ContentService.MimeType.JSON);

保存したら「新しいデプロイ」から「ウェブアプリ」を選択し、アクセスできるユーザーを「全員」にして保存してください。
すると、このようなURLが発行されます。
gas2.PNG

コピーして末尾に?word=englishを追加して飛んでみます。
gas4.PNG
無事、「english」の意味だけ抽出されました!(品詞名のノイズが入っていますが…)

Javascriptから取得してみる

意味を抽出してJSONを返してくれるAPIは完成したので、今度はローカルのJSからフェッチしてみます。※下ではReactを使用していますが、関数部分は生のjsでも同じはずです

const [answerList, setAnswerList] = useState([]);
const [word, onChangeWord] = useState('');
const url = 'https://script.google.com/macros/s/xxxxx/exec';

// urlに検索したい単語の文字列を追加してjsonをフェッチする
const fetchAnswer = async () => {
    const submitUrl = url + '?word=' + word;
    return fetch(submitUrl)
    .then(res => res.json());
}

// 検索ボタンを押したときにfetchAnswer関数を実行し、リストに入れる
const onPressFetch = () => {
    (async() => {
        setAnswerList(await fetchAnswer());
    })();
}

// 省略

<View>
    <Input onChangeText={onChangeWord} 
        value={word}
    />
    <Button title="検索" 
        onPress={onPressFetch} 
    />
</View>

Inputに入力された文字をパラメータとしてGASに渡し、GASが返却したJSONをfetchAnswerでフェッチしています。フェッチしたものをリストに入れて良い感じに表示すると下のようになりました!

gas5.gif

15
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
27