「税についての作文」において人気の単語を調べる

#はじめに
税についての作文がァ、宿題にね？宿題に出たんですよ。とりあえず過去に受賞した作文を[ググったら出てきたホームページらしきもの](https://www.nta.go.jp/taxes/kids/index.html)で調べてみたんですけど、なんかこう……**"統一感"**みたいなのを覚えると言いますか、判を押したよう、というかまぁ……はい。これを形態素解析したら面白い結果が得られそうなので、やっていこうかなと思います。はい。

#環境
* Ruby 2.7.0
* Python 3.8.3
* Nokogiri 1.10.9
* pdf-reader 2.4.0
* wordcloud 1.7.0
* mecab-python 1.0.1

#やる
##テキストデータとして取得
このホームページには平成29年度～令和元年度までに受賞した作文が載ってるので、こいつをダウンロードしてごちゃごちゃやる感じになると思います。なのでまずはスクレイピングでデータを入手しましょう。
ちなみに、**なぜか**令和元年度の中学生の作文だけHTMLベタ書きではなくPDFファイルとして用意されているため、令和元年度の中学生のものとその他で処理方法を分けることになります。ちなみにこの作文群だけ数が明らかに他と比べて多いので、PDF化している理由はその辺にありそうですね。

###HTMLにベタ書きされているデータを取得
さっき調べたところづもHTMLベタ書きデータも形式が**物によって違い**、ざっくり分けると**「平成30年度と令和元年度の高校生」**と**「その他」**で形式が違います。なんでこんな仕様にしたんだ？？？？？？？？
わかりやすく表にするとこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603574/9e77702b-9fc5-9185-8c3b-5b1ae4dc7dfa.png)
何がしたかったんだ

####平成29年度の両方と平成30年度の中学生
さっきの表で言うベタ書きAです。雑に書きました

```Ruby:text_dl_A.rb
require 'nokogiri'
require 'open-uri'

base_urls =["https://www.nta.go.jp/taxes/kids/sakubun/koko/h29/sakubun.htm",
            "https://www.nta.go.jp/taxes/kids/sakubun/chugaku/h29/sakubun.htm",
            "https://www.nta.go.jp/taxes/kids/sakubun/chugaku/h30/sakubun.htm"] #別にプログラム中でURLを生成してもよかったんですがめんどくさかったのでコピペで済ませます
count = 0
base_urls.each do |url|
    doc = Nokogiri::HTML(URI.open(url))
    doc.xpath("//p[@class='sakubun_texts']").each do |content|
        count += 1
        File.open("texts/#{count}.txt","w") do |f|
            f.puts content.inner_text
        end
    end
    sleep 1
end
```

####平成30年度と令和元年度の高校生
さっきの表で言うベタ書きBです、これまた雑

```Ruby:text_dl_B.rb
require 'nokogiri'
require 'open-uri'

base_urls =["https://www.nta.go.jp/taxes/kids/sakubun/koko/h30/sakubun.htm",
            "https://www.nta.go.jp/taxes/kids/sakubun/koko/r1/sakubun.htm"] 
count = 20
base_urls.each do |url|
    doc = Nokogiri::HTML(URI.open(url))
    doc.xpath("//p[@class='movePageTop']").each do |ptag|
        count += 1
        File.open("texts/#{count}.txt","w") do |f|
            f.puts ptag.previous.previous.inner_text #作文そのものにクラスやIDが設定されていなかったので「このページの先頭へ」ボタンから兄弟関係を探す方向で組みました
        end
    end
    sleep 1
end
```

これでベタ書きされたデータのダウンロードは完了です、全部で39ファイル落とせました
###PDFとして掲載されたデータを取得
####PDFファイルのURLを取得
とりあえずこういう感じのコードを書いて雑に取得しようかと思ったんですが、

```Ruby
require 'nokogiri'
require 'open-uri'

urls = []
doc = Nokogiri::HTML(URI.open("https://www.nta.go.jp/taxes/kids/sakubun/chugaku/r01/index.htm"))
doc.xpath("//td[@class='mvC left']/a[@target='_blank']").each do |atag|
    urls.push("https://www.nta.go.jp" + atag[:href])
end
puts urls
```

なんか途中で止まっちゃいました、どうもスクレイピングにおける"限界文字数"みたいなのに達したのかな？よくわからない、まあとにかくスクレイピングで取るのはなんかわかんないけどダメそうなのでもっと雑な方法でやります：

1. 令和元年度の中学生の作文の[目次のソース](view-source:https://www.nta.go.jp/taxes/kids/sakubun/chugaku/r01/index.htm)を表示
2. Ctrl+A→Ctrl+Cでコピー
3. さっきググったら出てきた[正規表現による文字列抽出Webアプリ](https://www.ipentec.com/utils/WebTextUtility/PatternExtract/)の「入力」欄に貼り付け
4. 「抽出パターン」欄に`(?<=href=")\/taxes\/kids\/sakubun\/chugaku\/r01\/pdf\/.+\.pdf`の正規表現を貼って「パターンマッチした指定のグループを抽出」で抽出実行
5. 御覧の通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603574/e3b6011d-b9af-a330-5920-6e4541733348.png)

素晴らしい。
こいつを適当に**urls.txt**みたいな名前のファイルに格納しておきます。

####URLからダウンロード
雑に書きました

```Ruby:pdf_dl.rb
require 'open-uri'

count = 0
File.foreach("urls.txt") do |f|
    count += 1
    url = "https://www.nta.go.jp" + f.chomp
    URI.open(url) do |dwn_f|
        File.open("pdfs/#{count}.pdf","wb") do |out|
            out.write(dwn_f.read)
        end
    end
    sleep 1
end
```

これで「pdfs」フォルダ下に130のPDFファイルがダウンロードできました、いや多くないか？明らかに量が異常

####PDF→TXT
pdf-readerってライブラリがあったのでこいつで変換します。

```ruby:pdf2txt
require 'pdf-reader'

Dir.glob("pdfs/*.pdf").each do |i|
    first_indent_flag = true
    text = ""
    reader = PDF::Reader.new(i)
    pdf = ""
    reader.pages.each do |page|
        pdf += page.text
    end
    pdf.each_line do |line|
        if first_indent_flag
            if /^ [^ ].*/ === line.scrub #「半角スペース一つのみによる字下げ」が最初に登場した地点で本文開始を判定
                first_indent_flag = false
                text += line
            end
        else
            text += line
        end
    end
    File.open("texts/#{i.match(/[0-9]+/)[0].to_i + 39}.txt","w") do |f|
        f.puts text
    end
end
```

もうちょっとなんとかならなかったのか
えーこのコードを実行することでtextsファイル直下に合計169個のテキストファイルが置かれると思います。多分どこかで多少取りこぼしてる気がするんですが、どこを零してるのかわからないのでなかったことにします。

##MecabでWordcloudに出力
Pythonでやります。[前に書いた記事](https://qiita.com/gaqwest/items/73eb2952e4aa51a5a98f)で書いたコードを使いまわします。

```Python
import MeCab
from wordcloud import WordCloud
t = MeCab.Tagger()
s = []

for i in range(1, 169):
    with open(f'texts/{i}.txt', encoding="UTF-8") as txt_file:
        text = txt_file.read()
    nodes = t.parseToNode(text)
    while nodes:
        if nodes.feature[:2] == "名詞":
            s.append(nodes.surface)
        nodes = nodes.next

wc = WordCloud(width=720, height=480, background_color="black", stopwords={
                "これ", "ため", "それ", "よう", "こと", "もの"}, font_path="C:\Windows\Fonts\HGRGE.TTC")
wc.generate(" ".join(s))
wc.to_file('test.png')
```

こういう画像が出力されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603574/6e73005f-cdc2-1c05-045a-ab2527341f08.png)
素晴らしい！かなり税についての作文って感じですね！色々考察もしたいんですがめんどくさくなってきたんで記事を畳みます、この画像一枚だけでかなり色々考えられると思うので皆さんもやってみてください！！！！では！！！！！
#まとめ
税金は生活に必要なものであることを医療に関することを踏まえて（この際祖父か祖母に言及しているとなお良し）書いたうえで「国民としての納税の義務を果たそう」みたいな感じで書くとよさそう、あと消費税への言及も忘れずに