【最強の英単語帳爆誕ww】Pythonでエンジニア必須の英単語帳を自動生成-前編




# はじめに
みなさん一度は購入したことがあると思います英単語帳をPythonで自動的に作成すれば、
<h3>もう英単語帳購入の必要はないんじゃないか？</h3>
という仮説を検証していきます。

</br>
</br>
**LGTMが10を超えたら**さらに実用的なものを後編（もしくは中編）で作成していきますので、面白かったらLGTMお願いします〜！


# 著者紹介

### 略歴
![256_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616192/1ee62833-e920-6cef-e051-a7ec8ae195af.png)


20才で高専の電気情報工学科を卒業後、技術商社で仕様書などの翻訳、海外メーカ来日時の通訳、法人営業などを行いながら、土日9時間と平日の1時間の英語の自己学習を1年ほど継続しTOEIC900超え、IELTS7.5を取得しました。
その後、ちょっと留学してみたいと思いマレーシアへ会計専攻で留学、留学前から久々にやりたかったプログラミング勉強も同時に開始し、友人などの知り合いから案件を少しずつ頂きはじめました。
在学中マレーシアで英会話講師とプログラミングの仕事を受け始めて収入が安定し、プログラミングにハマりでしたので大学中退し帰国、本格的にプログラマーとしてAIのモデル開発(python)、iOSアプリの開発(swiftUI)、そしてwebアプリケーション開発(django/flask)の仕事を頂いてきました。来年からは海外で仕事を始める予定をしております。
##### →[NEW]2021年にオランダに移住しました！

### 宣伝
Google翻訳でしか海外の文献などの一時情報にあたれない、英語でコミュニケーションが必要だけど英語話せないエンジニアの方々向けに英単語のクイズや、よくある変数の読み方、文献頻出単語、エンジニアであればよく使う英語フレーズなどを発信するアカウントをはじめました。これからは、海外のブログや文献の翻訳、英語学習におすすめのyoutuberやNetflixなども紹介していきます！気になった方はフォローお願いします！

Twitter：[ほし|Python](https://x.com/hosh_it_)


前置きが長くなりましたが、早速本題に入っていきたいと思います！

# 目次
- 何を作るのか？
- どのように作るのか？
- コード全体
    - コードの解説
        - HTMLデータを取得後、HTMLタグを削除
        - 形態素解析
        - 単語帳用にフィルター
        - 降順に並び替え後トップ50を表示
- 実行結果
- 改善点と改善方法
- 終わりに

# 何を作るか？
![coding.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616192/bb0236bf-4901-55c9-8b9f-4097a93e4604.jpeg)

単語帳を使用するそもそもの目的は
>「**達成したい目標のために必要なものだけを覚えるため**」

になります。qiita読者のみなさんはITエンジニアだと思いますので、
今回は**エンジニアの方が技術書を読めるようになるための英単語帳**を作成してみます。

# どのように作るか？
<img width="1322" alt="stackoverflow.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616192/5d6bc62f-e7a9-f098-892d-d9634e93fa7b.png">
1. StackoverflowからHTMLデータを取得
2. 形態素解析
3. 単語の頻出回数を計算
4. 頻出回数の多いものを候補として表示


今回は前編ということでまず「Python」というキーワードでタグ付けされた下記HTMLページ1画面分のみのデータを使用します。
https://stackoverflow.com/questions/tagged/python


それではコードの紹介に入っていきます。

# コード全体
コード全体はこのようになっています。

```python
from enum import Enum, unique
from typing import List, Tuple, Set, Dict
import requests

from bs4 import BeautifulSoup as bs
from textblob import TextBlob

URL = 'https://stackoverflow.com/questions/tagged/python'
PARSER = "html.parser"
FILTER_BY_COUNT = 2


@unique
class PartOfSpeechToLearn(Enum):
    JJ = 'Adjective'
    VB = 'Verb'
    NN = 'Noun'
    RB = 'Adverb'


if __name__ == '__main__':
    # Get HTML data and remove html tags
    res = requests.get(URL)
    raw_html = bs(res.text, PARSER)
    texts_without_html: str = raw_html.text

    # morphological analysis
    morph = TextBlob(texts_without_html)
    word_and_tag: List[Tuple[str, str]] = morph.tags

    # Filter words to create a book for vocab
    part_of_speech_to_learn = tuple(pos.name for pos in PartOfSpeechToLearn)
    words_to_learn: Set[str] = {
        wt[0]
        for wt in word_and_tag
        if wt[1] in part_of_speech_to_learn
    }
    words_filtered_by_count: Dict[str, int] = {
        word: morph.words.count(word)
        for word in words_to_learn
        if morph.words.count(word) > FILTER_BY_COUNT
    }

    # Show 50 words that are most frequently used
    words_in_descending_order: List[Tuple[str, int]] = sorted(
        words_filtered_by_count.items(),
        key=lambda x: x[1],
        reverse=True
    )
    for i, word_and_count in enumerate(words_in_descending_order[:50]):
        print(f'rank:{i} word: {word_and_count}')
```

## 単語帳のために取得する品詞(part of speech)を設定
今回は**下記の4つの品詞**を取得していきます。
1. **Adjective** (形容詞) bigやfunnyなどの名詞を修飾する品詞
2. **Verb** (動詞)動きを表す品詞 runやwriteなど
3. **Noun**　(名詞) Appleなど
4. **Adverb** (副詞) reallyやsurelyなどの形容詞や動詞を修飾する品詞

```python
@unique
class PartOfSpeechToLearn(Enum):
    JJ = 'Adjective'
    VB = 'Verb'
    NN = 'Noun'
    RB = 'Adverb'
```


## HTMLデータを取得後、HTMLタグを削除
URLからHTMLを取得して、HTMLタグ無しのテキストに変換しています。

```python
# Get HTML data and remove html tags
res = requests.get(URL)
raw_html = bs(res.text, PARSER)
texts_without_html: str = raw_html.text
```

## 形態素解析
単語帳に含める品詞を制限するために形態素解析を行います。形態素解析にはTextBlobを使用しています。TextBlobについては[こちら](https://textblob.readthedocs.io/en/dev/quickstart.html#part-of-speech-tagging)を適当に参照しました。

```python
# morphological analysis
morph = TextBlob(texts_without_html)
word_and_tag: List[Tuple[str, str]] = morph.tags
```

## 単語帳用にフィルター
単語帳に含めたい品詞だけでフィルター後、頻出回数でフィルタリング(FILTER_BY_COUNT=2)しつつ、単語をキー、出現回数をvalueとした辞書を作成。

```python
part_of_speech_to_learn = tuple(pos.name for pos in PartOfSpeechToLearn)
words_to_learn: Set[str] = {
    wt[0]
    for wt in word_and_tag
    if wt[1] in part_of_speech_to_learn 
}
words_filtered_by_count: Dict[str, int] = {
    word: morph.words.count(word)
    for word in words_to_learn
    if morph.words.count(word) > FILTER_BY_COUNT
}
```
## 降順に並び替え後トップ50を表示
```python
words_in_descending_order: List[Tuple[str, int]] = sorted(
    words_filtered_by_count.items(),
    key=lambda x: x[1],
    reverse=True
)

# Show 50 words that are most frequently used
for i, word_and_count in enumerate(words_in_descending_order[:50]):
    print(f'rank:{i} word: {word_and_count}')
```

# 実行結果
![surprise.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616192/3ba87aad-8aa3-ba47-2d8b-5c921decddd4.jpeg)

英単語帳となり得るのでしょうか...........................？

肝心の実行結果はこちら...........................! 



```shell
rank:0 word: ('i', 96)
rank:1 word: ('python', 86)
rank:2 word: ('ago', 50)
rank:3 word: ('bronze', 36)
rank:4 word: ('have', 29)
rank:5 word: ('×', 25)
rank:6 word: ('stack', 21)
rank:7 word: ('file', 17)
rank:8 word: ('List', 17)
rank:9 word: ('list', 17)
rank:10 word: ('data', 16)
rank:11 word: ('like', 14)
rank:12 word: ('be', 14)
rank:13 word: ('language', 13)
rank:14 word: ('pandas', 13)
rank:15 word: ('code', 12)
rank:16 word: ('create', 11)
rank:17 word: ('there', 10)
rank:18 word: ('dataframe', 10)
rank:19 word: ('not', 9)
rank:20 word: ('function', 9)
rank:21 word: ('silver', 9)
rank:22 word: ('work', 8)
rank:23 word: ('String', 8)
rank:24 word: ('string', 8)
rank:25 word: ('Get', 8)
rank:26 word: ('get', 8)
rank:27 word: ('r', 7)
rank:28 word: ('R', 7)
rank:29 word: ('tags', 7)
rank:30 word: ('following', 7)
rank:31 word: ('flask', 7)
rank:32 word: ('input', 7)
rank:33 word: ('do', 7)
rank:34 word: ('plot', 6)
rank:35 word: ('layout', 6)
rank:36 word: ('import', 6)
rank:37 word: ('array', 6)
rank:38 word: ('use', 6)
rank:39 word: ('below', 6)
rank:40 word: ('object', 6)
rank:41 word: ('format', 6)
rank:42 word: ('python-3.x', 6)
rank:43 word: ('app', 6)
rank:44 word: ('log', 5)
rank:45 word: ('add', 5)
rank:46 word: ('variable', 5)
rank:47 word: ('scrapy', 5)
rank:48 word: ('def', 5)
rank:49 word: ('c', 5)
```

ん〜ちょっと微妙ですね。ただ、ほぼ想定通りの結果です。

# 改善点と改善方法
![meeting_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616192/f658a6ab-b6ef-507e-99fb-46f4ef30b119.jpeg)


微妙な理由は以下の3点です。(続編執筆中に修正 更新4/23 11:57)

1. プログラムのみで使用する単語が存在する
2. case insensitiveになっていない
3. stackoverflowのページにオーバフィットしている

1の改善方法としては**前処理をもう少し高度にしていく必要**があります。
3に関しては、stackoverflowの個別質問ページや、その他技術ブログ、技術ニュースなども混ぜて**取得データを増やしていく必要がありそう**です。


# 終わりに
![coffee.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616192/1a42ef9f-21fd-614a-9890-43fad0b5d78c.jpeg)


**LGTMが10を越えれば**改善点を修正し次回の記事(中編か後編)を書いていきます。
そして単語帳が完成した場合、そのデータをみなさんにシェアして
<h3>実際に単語帳として活用できる形にしていきます！</h3>

なので、このシリーズが面白いと思ったら**ぜひLGTMお願いします！**


# 続編
（**LGTM10突破しました！！(ありがとうございます)**現在、次作の記事を執筆中ですが、LGTMの数だけ丁寧な記事が書けますので、引き続きイイねと思ったらLGTMお願い致します！　更新4/23 9:00)

後編書きました！こちらからどうぞ！
[【最強の英単語帳爆誕ww】Pythonでエンジニア必須の英単語帳を自動生成-後編](https://qiita.com/hossyan_eng/items/172feadf85845f25ce58)