Pythonで反義語の辞書を作る

## 反義語とは
反義語(antonym)とは「good⇔bad」のように反対の意味を持つ単語になります。
今回自作予定のアプリに英単語の反義語が必要になったため、作成する事にしました。

## 元の英単語
https://www.jamsystem.com/ancdic/index.html
今回はこちらの辞典から元となる英単語を取得することにしました。
約３万後あります。

## 反義語を得るためのアプローチ
今回反義語を得るために3つのアプローチを考えました。
①外部APIを使う
②pythonの外部ライブラリを使う
③WEBからスクレイピング
これらのプログラムを使ってExcelの表に反義語を記載していきたいと思います。


### 外部APIを使う
今回RapidApiで提供されている「Synonyms」というAPIを使用しました。
コードは以下になります。これで３万語約半数が埋まりました。
なお万単位の処理をするのは時間がかかるため、途中でやめてもいいように毎回エクセルを保存しています。
これをしないで、途中で処理を止めないといけなくなりまた一からやり直しということが何回もありました。（全て処理するのに10時間くらいかかりました）

```Synonyms.api
import requests
import re
# エクセルを操作するためのライブラリ
from openpyxl import Workbook,load_workbook
import time

print("スタート")
wb = load_workbook('antonyum_dic.xlsx')
ws = wb['sheet1']

headers = {
	"X-RapidAPI-Key": "XXXX",
	"X-RapidAPI-Host": "XXXX"
}

count = 0
for i in range(101,1100):
  baseWord = ws[f'A{i}'].value
  antonymsWord = ws[f'B{i}'].value
  if baseWord != "" and antonymsWord == "none":
    url = f'https://languagetools.p.rapidapi.com/antonyms/{baseWord}'
    response = requests.request("GET", url, headers=headers)
    try:
      antonym_results = response.text["antonyms"][0]
    except:
      pass
    else:
      if len(antonym_results)<=50 and len(antonym_results)>1:
        print(antonym_results)
        ws[f'B{i}'] = antonym_results
        count = count + 1
        wb.save('antonyum_dic.xlsx')
      else:
        pass

wb.save('antonyum_dic.xlsx')
print(f'処理が完了しました。{count}個の反義語が見つかりました')
```

### pythonの外部ライブラリを使う
pypi で「antonym」と検索したところ43件がヒットしました。
半分くらいは反義語を取得するためのものではなかったです。
使えそうなライブラリを1つ1つスターの数や使っている元の辞書などを見て良さそうなものを3個程使ってみました。
ほとんどのライブラリに登録されているのがAPIで取ってきた単語と同じらしく３つ使って5000個位しか埋まりませんでした
以下が使ったライブラリのプログラムです。
基本的なやり方は一緒なのですが、後から気づいて修正をかけたりしているので、若干細かいところが違います。
また単語が見つからない時のエラー内容も異なるため対処の方法も変えています。
（何気にここが今回の内容で1番勉強になったところかも

wordhoardを使った例

```wordhoard.py
from wordhoard import Antonyms
import re
# エクセルを操作するためのライブラリ
from openpyxl import Workbook,load_workbook
import re
import time

print("スタート")
wb = load_workbook('antonyum_dic.xlsx')
ws = wb['sheet1']


# 正規表現を使ってエラー処理をする
_ILLEGAL_CHARACTERS_RE = re.compile(r"[\000-\010]|[\013-\014]|[\016-\037]")

count = 0
for i in range(1,100):
  baseWord = ws[f'A{i}'].value
  antonymsWord = ws[f'B{i}'].value
  if baseWord != "" and antonymsWord == "none":
    antonym = Antonyms(search_string=baseWord)
    try:
      antonym_results = antonym.find_antonyms()[0]
    except:
      pass
    else:
      if len(antonym_results)<=50 and len(antonym_results)>1:
        # print(antonym_results)
        fixed_antonym =_ILLEGAL_CHARACTERS_RE.sub("", antonym_results)
        ws[f'B{i}'] = fixed_antonym
        count = count + 1
        wb.save('antonyum_dic.xlsx')
      else:
        pass

wb.save('antonyum_dic.xlsx')
print(f'処理が完了しました。{count}個の反義語が見つかりました')

```


PyDictAPIを使った例

``` PyDictAPI.py
from PyDictAPI import Finder
Meanings = Finder()
# エクセルを操作するためのライブラリ
from openpyxl import Workbook,load_workbook
import re

print("スタート")
# エクセルファイルを開く
wb = load_workbook('antonyum_dic.xlsx')
ws = wb['sheet1']

count = 0
for i in range(5701,15700):
  baseWord = ws[f'A{i}'].value
  if baseWord != "":
    antonymsWord = ws[f'B{i}'].value
    if antonymsWord == "none":
      try:
        antonymsResult = Meanings.findAntonyms(baseWord, 1)[0]
      except:
        pass
      else:
        res = re.match("^Couldn't.*", antonymsResult)
        if res is None:
          # 反義語が見つかった回数をカウントする
          count = count + 1
          # print(antonymsResult)
          ws[f'B{i}'] = antonymsResult
          wb.save('antonyum_dic.xlsx')
        else:
          pass

print(f'処理が完了しました。{count}個の反義語が見つかりました')

```

PyMultiDictionaryを使った例

```PyMultiDictionary.py
from PyMultiDictionary import MultiDictionary
# エクセルを操作するためのライブラリ
from openpyxl import Workbook,load_workbook

dictionary = MultiDictionary()

# エクセルファイルを開く
wb = load_workbook('antonyum_dic.xlsx')
ws = wb['sheet1']

for i in range(28001,32000):
  baseWord = ws[f'A{i}'].value
  if baseWord != "":
    antonymsWord = ws[f'B{i}'].value
    if antonymsWord == "none":
      try:
        dictionary.antonym('en',baseWord)[0]
      except:
        pass
      else:
        ws[f'B{i}'] = dictionary.antonym('en',baseWord)[0]
        wb.save('antonyum_dic.xlsx')

print("処理が完了しました")
```

### ③WEBからスクレイピング
残った単語は、反義語が載っているサイトからスクレイピングしてきました。
プログラムは載せませんが、反義語が載っているサイトは意外と少なく苦労しました。
学校の研究室などが多い印象です。
ちなみにこれでも全部は埋まりませんでした　

### 最終手段（人力）
①〜③でも埋まらない単語があったので、最後は一つ一つ人力で考えて埋めていきました。
例えば建築という意味のarchitectureが見つからなかったので、廃墟の意味のruinsにしました。
（あってるかどうかはわからない、笑）
これでやっと全単語埋めることができました。

## 今後
今後は、調べた辞書をいつでも自由に取り出せるようにシステム化していきたいと思います。
（APIなどを検討中）
またシステム化の前に、単語同士の類似度を調べたら面白いのではと思っています。
（全く類似しない０になるはず？）
色んなライブラリを使ったり、スクレイピングするのは時間がかかりましたたが、ライブラリの違いや
色んなPythonの書き方が知れてとても楽しかったです。
今後も何か作っていきたいと思います。