はじめに
みなさん一度は購入したことがあると思います英単語帳をPythonで自動的に作成すれば、
もう英単語帳購入の必要はないんじゃないか?
という仮説を検証していきます。
LGTMが10を超えたらさらに実用的なものを後編(もしくは中編)で作成していきますので、面白かったらLGTMお願いします〜!
著者紹介
略歴
20才で高専の電気情報工学科を卒業後、技術商社で仕様書などの翻訳、海外メーカ来日時の通訳、法人営業などを行いながら、土日9時間と平日の1時間の英語の自己学習を1年ほど継続しTOEIC900超え、IELTS7.5を取得しました。現在はバックエンドとAIエンジニアを本業に英会話講師を副業でやっています。詳しくはこちらをご覧ください。https://hossyan-blog.com/profile/
宣伝
一昨日プログラマー向けの英語学習サイトをオープンしました。英語学習をこれから始めようとしている方、また学習方法について悩んでいる方などに読んでいただけるブログになっていますのでぜひご覧ください。https://hossyan-blog.com/
前置きが長くなりましたが、早速本題に入っていきたいと思います!
目次
- 何を作るのか?
- どのように作るのか?
- コード全体
- コードの解説
- HTMLデータを取得後、HTMLタグを削除
- 形態素解析
- 単語帳用にフィルター
- 降順に並び替え後トップ50を表示
- コードの解説
- 実行結果
- 改善点と改善方法
- 終わりに
何を作るか?
こちらでも紹介していますが、単語帳を使用するそもそもの目的は
「達成したい目標のために必要なものだけを覚えるため」
になります。qiita読者のみなさんはITエンジニアだと思いますので、
今回はエンジニアの方が技術書を読めるようになるための英単語帳を作成してみます。
どのように作るか?
1. StackoverflowからHTMLデータを取得
2. 形態素解析
3. 単語の頻出回数を計算
4. 頻出回数の多いものを候補として表示
今回は前編ということでまず「Python」というキーワードでタグ付けされた下記HTMLページ1画面分のみのデータを使用します。
https://stackoverflow.com/questions/tagged/python
それではコードの紹介に入っていきます。
コード全体
コード全体はこのようになっています。
fromenumimportEnum,uniquefromtypingimportList,Tuple,Set,Dictimportrequestsfrombs4importBeautifulSoupasbsfromtextblobimportTextBlobURL='https://stackoverflow.com/questions/tagged/python'PARSER="html.parser"FILTER_BY_COUNT=2@uniqueclassPartOfSpeechToLearn(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.nameforposinPartOfSpeechToLearn)words_to_learn:Set[str]={wt[0]forwtinword_and_tagifwt[1]inpart_of_speech_to_learn}words_filtered_by_count:Dict[str,int]={word:morph.words.count(word)forwordinwords_to_learnifmorph.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=lambdax:x[1],reverse=True)fori,word_and_countinenumerate(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などの形容詞や動詞を修飾する品詞
@uniqueclassPartOfSpeechToLearn(Enum):JJ='Adjective'VB='Verb'NN='Noun'RB='Adverb'
HTMLデータを取得後、HTMLタグを削除
URLからHTMLを取得して、HTMLタグ無しのテキストに変換しています。
# 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についてはこちらを適当に参照しました。
# morphological analysis
morph=TextBlob(texts_without_html)word_and_tag:List[Tuple[str,str]]=morph.tags
単語帳用にフィルター
単語帳に含めたい品詞だけでフィルター後、頻出回数でフィルタリング(FILTER_BY_COUNT=2)しつつ、単語をキー、出現回数をvalueとした辞書を作成。
part_of_speech_to_learn=tuple(pos.nameforposinPartOfSpeechToLearn)words_to_learn:Set[str]={wt[0]forwtinword_and_tagifwt[1]inpart_of_speech_to_learn}words_filtered_by_count:Dict[str,int]={word:morph.words.count(word)forwordinwords_to_learnifmorph.words.count(word)>FILTER_BY_COUNT}
降順に並び替え後トップ50を表示
words_in_descending_order:List[Tuple[str,int]]=sorted(words_filtered_by_count.items(),key=lambdax:x[1],reverse=True)# Show 50 words that are most frequently used
fori,word_and_countinenumerate(words_in_descending_order[:50]):print(f'rank:{i} word: {word_and_count}')
実行結果
英単語帳となり得るのでしょうか...........................?
肝心の実行結果はこちら...........................!
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)
ん〜ちょっと微妙ですね。ただ、ほぼ想定通りの結果です。
改善点と改善方法
微妙な理由は以下の点です。
- iとかx、defなどの単語が入ってきている
- プログラム内で使用する単語が多い(これはある意味okですが)
- case insensitiveになっていない
- 超簡単な英単語しか無い
- stackoverflowのページにオーバフィットしている
1~3の改善方法としては前処理をもう少し高度にしていく必要があります。
4に関しては英単語帳作成前にある程度人力で必要無さそうな単語を見ていく必要がありそうです。もしくは、簡単な英単語を集めてきてフィルターにかけるのもありです。
最後の5に関しては、stackoverflowの個別質問ページや、その他技術ブログ、技術ニュースなども混ぜて取得データを増やしていく必要がありそうです。
終わりに
LGTMが10を越えれば改善点を修正し次回の記事(中編か後編)を書いていきます。
そして単語帳が完成した場合、そのデータをみなさんにシェアして
実際に単語帳として活用できる形にしていきます!
なので、このシリーズが面白いと思ったらぜひLGTMお願いします!
続編
(LGTM10突破しました!!(ありがとうございます)現在、次作の記事を執筆中ですが、LGTMの数だけ丁寧な記事が書けますので、引き続きイイねと思ったらLGTMお願い致します! 更新4/23 9:00)