発音記号を表形式でまとめる（米語、英語、独語）

# はじめに
本記事は、こちらのサイト( http://stabucky.com/wp/archives/7345 )を参考にさせていただきました。ありがとうございました！

# 概要
外国語の曲を歌う中で発音記号があると大変便利ですが、いちいち調べていると大変時間がかかる…。
ということで、自動で発音記号を埋めてくれるアプリを作成しました。

# 完成イメージ
<img width="1011" alt="スクリーンショット 2017-12-02 21.23.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/219684/e75aee4f-a2d0-4b76-95f5-6cfb8b83b0b1.png">

<img width="910" alt="スクリーンショット 2017-12-02 21.24.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/219684/422b43cb-42be-de72-b10b-a1ef4c6a82e4.png">

# 仕様およびコード
- 「単語」欄に調べたい単語群を配置します。カンマやピリオドは省いてください。
- デフォルトでは、シート名を「発音対訳（英）」「発音対訳（独）」に設定する必要があります。
- コードをそのままの状態で動かすためには、上記「完成イメージ」通りのレイアウトにする必要があります。
- 発音記号は辞書サイトから取ってきていますが、正しいものが取得できるとは限りません（例えば、上記イメージでは"goes"のイギリス英語発音が"ɡuːs"となっています）。

```js:create_pron_list.gs
/***********************************
機能：発音記号表を作成する（英語）
入力：void
出力：void
************************************/
function pronunciation_list() {
  var sheet, array, word, prons;
  sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("発音対訳（英）");
  array = findRow(sheet);
  
  // 操作対象列の数だけ繰り返す
  for (var j = 0; j < array.length; j++) {
    
    // 要素が無くなるまで繰り返す
    for (var i = 2; sheet.getRange(array[j], i).getValue() != ""; i++) {
    
      // 単語を取得する
      word = sheet.getRange(array[j], i).getValue();
      
      // 発音記号を取得する
      prons = fetch_pronunciation(word);
      
      // 発音記号を出力する
      for (var k = 0; k < prons.length; k++) {
        sheet.getRange(array[j] + k + 1, i).setValue(prons[k]);
      }
    }
  }
}

/***********************************
機能：発音記号表を作成する（独語）
入力：void
出力：void
************************************/
function pronunction_list_german() {
  var sheet, array, word, pron;
  sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("発音対訳（独）");
  array = findRow(sheet);
  
  // 操作対象列の数だけ繰り返す
  for (var j = 0; j < array.length; j++) {
    
    // 要素が無くなるまで繰り返す
    for (var i = 2; sheet.getRange(array[j], i).getValue() != ""; i++) {
    
      // 単語を取得する
      word = sheet.getRange(array[j], i).getValue();
      
      // 発音記号を取得する
      pron = fetch_pronunciation_german(word);
      
      // 発音記号を出力する
      sheet.getRange(array[j] + 1, i).setValue(pron);
    }
  }
}

/***********************************
機能：単語に対して発音記号を出力する
入力：単語
出力：発音記号（米・英）
************************************/
function fetch_pronunciation(word) {
  var url, response, list, br_str, am_str, br_ms, am_ms, prons, i, flag, parts, count;
  url = "https://www.collinsdictionary.com/dictionary/english/"; // 利用する辞書サイトのURL
  flag = false; // fetch可否フラグ
  count = 0; // fetch試行回数
  prons = []; // 返却値
  
  // 単語詳細ページのfetchを最大10回試みる
  while (flag == false && count < 10) {  
    try {
      response = UrlFetchApp.fetch(url + word);
      flag = true;
    } catch (e) {
      count++;
    }
  }
  
  // HTML文をfetchする
  list = response.getContentText();
  
  // アメリカ英語、イギリス英語に関する記載がある部分を抜き出す
  am_str = list.match(/in American<\/span> <span class="homnum">1<\/span>(.*[\s\S]*)/);
  br_str = list.match(/in British<\/span> <span class="homnum">1<\/span>(.*[\s\S]*)/);
  
  // 上記で取得できなかった場合、条件を緩めて再度検索する
  if (am_str == null) {
    am_str = list.match(/in American<\/span>(.*[\s\S]*)/);
  }
  if (br_str == null) {
    br_str = list.match(/in British<\/span>(.*[\s\S]*)/);
  }
  
  // 発音の記載部分を抜き出す
  if (am_str.length > 1) {
    am_ms = am_str[1].match(/<span class="pron type-ipa">(.*?)</);
  }
  if (br_str.length > 1) {
    br_ms = br_str[1].match(/<span class="pron type-">(.*?)</);
  }
  
  // 発音記号を抽出する
  if (am_ms.length > 1) {
    prons.push(am_ms[1]);
  }
  if (br_ms.length > 1) {
    prons.push(br_ms[1]);
  }

  return prons;
}

/***********************************
機能：単語に対して発音記号を出力する
入力：単語
出力：発音記号（独）
************************************/
function fetch_pronunciation_german(word) {
  var url, response, list, str, ms, pron, i, flag, parts, count;
  url = "https://www.collinsdictionary.com/dictionary/german-english/"; // 利用する辞書サイトのURL
  flag = false; // fetch可否フラグ
  count = 0; // fetch試行回数
  pron = ""; // 返却値
  
  // 単語詳細ページのfetchを最大10回試みる
  while (flag == false && count < 10) {  
    try {
      response = UrlFetchApp.fetch(url + word);
      flag = true;
    } catch (e) {
      count++;
    }
  }
  
  // HTML文をfetchする
  list = response.getContentText();
  
  str = list.match(/<h2 class="h2_entry">(.*?)<\/h2>(.*[\s\S]*)/);
  
  try {
    // 発音の記載部分を抜き出す
    if (str.length > 2) {
      ms = str[2].match(/<span class="pron"> \((.*?)</);
    }
  
    // 発音記号を抽出する
    if (ms.length > 1) {
      pron = ms[1];
    }
  } catch (e) {
  }
  return pron;
}

/***********************************
機能：シート内から、操作対象となる列を取得
入力：シート名
出力：操作対象列（配列）
************************************/
function findRow(sheet){ 
  
  // 対象シートの最終行を取得
  var lastRow = sheet.getDataRange().getLastRow();
  var array = []
 
  // 行数分繰り返す
  for(var i = 1; i <= lastRow; i++){
    
    // 「単語」が記載された列を発見した時
    if(sheet.getRange(i,1).getValue() === "単語"){
      
      // 操作対象列に加える
      array.push(i);
    }
  }
  
  // 操作対象列を返却する
  return array;
}
```

# おわりに
帰宅して数時間で書いたものなのでテストもロクにしていません。ぜひ改良お願いします。ついでにフランス語とかロシア語とか追加してほしいな…