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


はじめに

税についての作文がァ、宿題にね?宿題に出たんですよ。とりあえず過去に受賞した作文をググったら出てきたホームページらしきもので調べてみたんですけど、なんかこう……"統一感"みたいなのを覚えると言いますか、判を押したよう、というかまぁ……はい。これを形態素解析したら面白い結果が得られそうなので、やっていこうかなと思います。はい。

環境

  • 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年度と令和元年度の高校生」「その他」で形式が違います。なんでこんな仕様にしたんだ????????
わかりやすく表にするとこんな感じです。


何がしたかったんだ

平成29年度の両方と平成30年度の中学生

さっきの表で言うベタ書きAです。雑に書きました

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です、これまた雑

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を取得

とりあえずこういう感じのコードを書いて雑に取得しようかと思ったんですが、

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. 令和元年度の中学生の作文の目次のソースを表示
  2. Ctrl+A→Ctrl+Cでコピー
  3. さっきググったら出てきた正規表現による文字列抽出Webアプリの「入力」欄に貼り付け
  4. 「抽出パターン」欄に(?<=href=")\/taxes\/kids\/sakubun\/chugaku\/r01\/pdf\/.+\.pdfの正規表現を貼って「パターンマッチした指定のグループを抽出」で抽出実行
  5. 御覧の通り

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

URLからダウンロード

雑に書きました

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ってライブラリがあったのでこいつで変換します。

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でやります。前に書いた記事で書いたコードを使いまわします。

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')

こういう画像が出力されます

素晴らしい!かなり税についての作文って感じですね!色々考察もしたいんですがめんどくさくなってきたんで記事を畳みます、この画像一枚だけでかなり色々考えられると思うので皆さんもやってみてください!!!!では!!!!!

まとめ

税金は生活に必要なものであることを医療に関することを踏まえて(この際祖父か祖母に言及しているとなお良し)書いたうえで「国民としての納税の義務を果たそう」みたいな感じで書くとよさそう、あと消費税への言及も忘れずに