17
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

自分のQiita記事をスクレイピングしてワードクラウドを作る

Posted at

はじめに

エンジニアになって半年が経過したので、振り返りのために、今まで投稿してきた記事のテキストデータをスクレイピングで取得して、ワードクラウドを作ってみました。
その際の手順を残したいと思います。

完成形

こんなのができました。
スクリーンショット 2020-05-08 10.43.08.png
「コンポーネント」とでっかく出ているのは恐らくVue.js「コンポーネント」入門でコンポーネントコンポーネント言いまくってるからですね。後はherokuとかDockerとかFlaskとか、そういえば記事書いたなぁというものがちょこちょこあり、懐かしい気持ちになりました。「変更」や「追加」といった汎用的な言葉が多く出ているので、お好みによってストップワード設定しても良いかもですね。
ちなみに、自分のはてなブログの方も同様にスクレイピングしてワードクラウドを作ってみました。こちらはTwitterのヘッダー画像にしているので、ぜひ見てみてください。(全然違うこと書いてあって面白いですね。)

環境

  • Mac
  • Python3

を使って作成していきます。

大まかな手順

  1. スクレイピングしてテキストデータを取得
  2. 形態素解析器(MeCab)を通して単語に分割する
  3. ワードクラウドを作成する

という手順で進めます。

スクレイピング

Qiita APIget itemsを使用します。
RequestURLの構文は以下の通りです。

https://qiita.com/api/v2/items?page={{ページ番号}}&per_page={{1ページあたりの記事数}}&query=user%3A{{ユーザID}}

例えば、私(kiyokiyo_kzsby)の記事を100記事取得したい場合は、以下のリクエストを送ればOKです。

https://qiita.com/api/v2/items?page=1&per_page=100&query=user%3Akiyokiyo_kzsby

レスポンスはJSON形式で返ってきます。

[
  {
    "rendered_body": "<h1>Example1</h1>",
    (略)
    "title": "Example title 1",
    (略)
  },
  {
    "rendered_body": "<h1>Example2</h1>",
    (略)
    "title": "Example title 2",
    (略)
  },
  ・・・
]

この中からrendered_bodytitleを抜き出してワードクラウドに利用します。

上記のコードをPythonのコードに落とし込むと、このようになります。

qiita_scraper.py
import requests
import json
from bs4 import BeautifulSoup

def scrape_all(user_id):
    text = ""
    r = requests.get("https://qiita.com/api/v2/items?page=1&per_page=100&query=user%3A" + user_id)
    json_list = json.loads(r.text)
    for article in json_list:
        print("scrape " + article["title"])
        text += article["title"]
        content = article["rendered_body"]
        soup = BeautifulSoup(content, "html.parser")
        for valid_tag in soup.find_all(["p","li","h1","h2","h3","h4","table"]):
            text += valid_tag.text
    return text

requestsはHTTPリクエストを実行するライブラリ、jsonはJSONを取り扱うライブラリ、BeautifulSoupはhtmlを取り扱うライブラリです。それぞれpip installで入れておきましょう。(BeautifulSoupに関してはこちらの記事が詳しくて良いです。)

$ pip install requests
$ pip install json
$ pip install beautifulsoup4

下から3行目のsoup.find_all(["p","li","h1","h2","h3","h4","table"])で、読み取るhtmlタグを指定しています。当初は全テキストを読み取ろうとしたのですが、埋め込んだコードも含まれてしまい、結果作成したワードクラウドがforとかifとかコードでよく出てくるワードばっかになってしまったので、テキスト部だけを抜き出すべくこのような指定をしています。この辺はお好みで調整してください。

形態素解析

スクレイピングした日本語テキストは英語と違って単語に分割されてないため、そのままワードクラウド生成ライブラリに突っ込んでもうまくいきません。そのため、形態素解析を行って単語に分割(分かち書き)します。今回はMecabという形態素解析器を使用します。こちらの記事をかなり参考にさせていただきました。

まずMecabの導入に必要なライブラリをインストールします。

brew install mecab mecab-ipadic git curl xz

次に、Mecab本体の導入をします。

brew install mecab mecab-ipadic

terminalでmecabと打って、文章を入力すると、形態素解析を実行してくれます。(終了はControl+C)

$ mecab
すもももももももものうち
すもも	名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
うち	名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS

これで準備は完了です。後はPythonで形態素解析を実行するコードを書きましょう。Pythonのコードはこちらの記事を参考にさせていただきました。

mecab.py
import MeCab as mc

def mecab_analysis(text):
    print("start mecab analysis")
    t = mc.Tagger('-Ochasen')
    node = t.parseToNode(text)
    output = []
    while(node):
        if node.surface != "":
            word_type = node.feature.split(",")[0]
            if word_type in ["形容詞","名詞"]:
                output.append(node.surface)
        node = node.next
    print("end mecab analysis")
    return output

MeCabのライブラリを使用するので、pip installしておきましょう。

$ pip install mecab-python3

下から5行目のif word_type in ["形容詞","名詞"]:で、outputに含める単語を「形容詞」と「名詞」に限定しています。副詞や動詞を含めたければこの配列に追加することで対応できます。

ワードクラウドの作成

前工程まででスクレイピングしたテキストを単語に分割することができたので、最後にワードクラウドのライブラリに突っ込んで完成させましょう。
まずワードクラウドライブラリのREADMEに従って、pip installしましょう。
また、画面描画用のライブラリmatplotlibもインストールしましょう。

$ pip install wordcloud
$ pip install matplotlib

続いて、以下のようにPythonのコードを書きます。Pythonのコードはこちらの記事を参考にさせていただきました。

word_cloud.py
import matplotlib.pyplot as plt
from wordcloud import WordCloud

def create_wordcloud(text):
    print("start create wordcloud")

    # 環境に合わせてフォントのパスを指定する。
    fpath = "/System/Library/Fonts/ヒラギノ明朝 ProN.ttc"

    # ストップワードの設定
    stop_words = [ u'てる', u'いる', u'なる', u'れる', u'する', u'ある', u'こと', u'これ', u'さん', u'して', \
             u'くれる', u'やる', u'くださる', u'そう', u'せる', u'した',  u'思う',  \
             u'それ', u'ここ', u'ちゃん', u'くん', u'', u'',u'',u'',u'',u'', u'', u'', u'', u'', u'', \
             u'ない', u'', u'', u'', u'', u'ので', u'よう', u'', u'もの', u'今週', u'まとめ',u'ため', \
             u'指定', u'場合', u'以下', u'作成', u'よう', u'部分', u'ファイル', u'利用', u'使用']

    wordcloud = WordCloud(background_color="white",font_path=fpath, width=800, height=500, \
                          stopwords=set(stop_words)).generate(text)
    print("end create wordcloud")

    print("now showing")
    plt.figure(figsize=(15,12))
    plt.imshow(wordcloud)
    plt.axis("off")
    plt.show()

上から6行目のfpath = "/System/Library/Fonts/ヒラギノ明朝 ProN.ttc"の部分でフォントのパスを指定しています。使用しているPCによってパスやフォント名が違う可能性があるので、適宜調整してください。
上から8行目のstop_words =以降でストップワードの指定をしています。ここで記載された単語はワードクラウド上に表示されなくなります。「もの」や「こと」など意味が無いけど頻度が多くてデカデカと表示されてしまう単語はここで指定してあげましょう。

最後にこれらをまとめてスクレイピング〜ワードクラウドの生成までを一括処理するファイルを作成しましょう。

main.py
from qiita_scraper import scrape_all
from mecab import mecab_analysis
from word_cloud import create_wordcloud

text = scrape_all("kiyokiyo_kzsby")
wordlist = mecab_analysis(text)
create_wordcloud(" ".join(wordlist))

4行目のscrape_allの引数にQiitaのuser_idを渡してあげています。ここを変えてあげることで別のユーザのワードクラウドを作成することもできます。

main.pyを実行すると、ログにこんな感じのメッセージが吐き出された後、ワードクラウドの画面が開きます。

scrape GoFのデザインパターンを勉強する
scrape DDDの頻出用語をなんとなく理解する
(中略)
scrape AtCoder400点アルゴリズムまとめ(Java編)
scrape AWS ソリューションアーキテクト-アソシエイトを取りたい
start mecab analysis
end mecab analysis
start create wordcloud
end create wordcloud
now showing

はいどーん!!
スクリーンショット 2020-05-08 10.43.08.png

実際はここから品詞やストップワードの調整をして、完成になると思います。楽しいのでぜひ色々といじってみてください。

おわりに

ワードクラウド作ってみるとどういうアウトプットをしてきたのか視覚的に分かるので良いですね。スクレイピングする対象をはてなブログとかTwitterとかに変えてみてもまた違った結果が出てきて面白いと思います。

17
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?