ゼロからWebスクレイピングで得られたデータを形態素解析で可視化する

# 初めに
**Webスクレイピング**してますか？私は最近までしてこなかったんです。色々理由があるんですが、一番は**よくわからない**から！笑そこで今回はWebスクレイピングとは何か？**危険性**はあるのか？どんな風に使うのか？について記事を作成しようと思います。私は機械学習を学ぶ過程で様々な技術に触れてきているので（**まだ初学者の域を脱せて無いですが。。。**）、その経験を踏まえてなるべくわかりやすく記事をまとめていきます。Webスクレイピングに興味がある方、興味があるけどやったことがない方はぜひ最後まで見ていってください。(^ ^)

https://github.com/seiji1997/Qiita/blob/master/%E5%BD%A2%E6%85%8B%E7%B4%A0%E8%A7%A3%E6%9E%90/%E5%BD%A2%E6%85%8B%E7%B4%A0%E8%A7%A3%E6%9E%90.ipynb

**今回は5本の章立てで書いています。**

+ 1, Webスクレイピング（Web scraping）とは？
+ 2, スクレイピングする時の注意点
+ 3, 実際にWebスクレイピングをしてみる
+ 4, 最後に
+ 5, 参考文献

#1, Webスクレイピング（Web scraping）とは？
スクレイピングとは、Web サイトで公開されている情報の中から特定の情報だけを抽出するコンピューターソフトウェア技術のことです。データの多くはHTML形式の非構造化データで、これをスプレッドシートやデータベースの構造化データに変換することで、さまざまなアプリケーションに利用することができます。これにより、手動でデータを収集する際にかかる手間や時間の大幅な削減が可能です。例えば以下のようなことができます！

+ 検索順位を定期的に自動収集
+ ショップサイトの商品価格、商品レビューを自動収集
+ 宿泊サイトの空室情報を自動収集
+ ネットオークションの価格変動を自動収集
+ 株価の変動を自動収集

しかし、スクレイピングは一歩間違えると迷惑行為や違法行為にもなり得る手法であり、正しく理解した上で扱わなければいけません。私も怖いので**ちゃんと調べてから**行うようにしました！

#2, スクレイピングする時の注意点
まず有名なものに[Librahack事件](https://ja.wikipedia.org/wiki/岡崎市立中央図書館事件)がありますね。ここで注意しないといけないのは**誤った使い方をしてはいけない！**ということです。スクレイピングに関して以下の2点は最も気をつける必要があると思います。

+ **スクレイピングを高頻度で行うことで対象サイトに対する負荷が膨大になる**
+ **スクレイピングにより取得した情報を不正に使用する**
+ **利用目的を明確にして利用する（情報解析など）**
+ **オープンライセンスのものを対象にする**
+ **利用規約をよく読む**

私たちがスクレイピングを使用する時には「著作権法上の問題」「利用規約との抵触」「サーバーへの過度なアクセス」を考えた方が良さそうです。[こちらのサイト](https://topcourt-law.com/internet_security/scraping-illegal)が非常に参考になりました！ありがとうございます！

###「著作権法上の問題」

著作権法では以下のような例外が認めてられています。
**「情報解析を目的とした記録または翻案」**
コンピュータで情報解析をすることが目的である場合には、例外的に著作権者の同意を得ることなく、スクレイピングによって取得した他社情報などを記録媒体に記録したり翻案（取得した情報に新たに表現を加えること）することができます。しかし、以下の点は違法になる可能性があるので注意しましょう。

**取得情報を複製した物の譲渡**
スクレイピングによって取得した情報を他人に譲渡することは、著作権法上禁じられています。なので、スクレイピングで情報を取得した場合、取得した情報を自分で独自に分析したうえで、再構成する必要があります。

**目的外利用**
情報解析目的以外の目的で利用した場合には、著作権法に違反することになります。なので、スクレイピングをする時は、あくまで「情報解析」を目的としたものでなければなりません。

###「利用規約との抵触」
利用規約を読んで、「スクレイピングを禁止します」「これに違反してスクレイピングをした場合には、損害を賠償してもらいます」といった記載がなければ問題はありません。私が思うに、一般に公開されていて、有料の会員登録や、特定のユーザーのみに公開されている限定的なものでなければ、利用規約に「スクレイピングを禁止」という文言は含まれていない気がします。☜ですが、怖いのでスクレイピングをする前には必ず調べましょう。

###「サーバーへの過度なアクセス」
私もスクレイピングを実行する際に気を付けているのが**アクセスの頻度**です。Webサイトへの過度なアクセスを直接禁止する法律は無いらしいのですが、サーバーに過度の負荷を与えることでLibrahack事件のように「偽計業務妨害罪」になる可能性もあります。この時は１秒に１回の頻度で１日2000回のスクレイピングを実行したようですが、サーバーの負荷的にはどうなのでしょう。

とりあえず以下のように1秒待機していれば大丈夫なんですかね？。。。

```python
time.sleep(1)
```

#3, 実際にWebスクレイピングをしてみる

## 歌ネットの[利用規約]

今回は歌ネットから歌詞データをスクレイピングしてきて形態素解析で可視化したいと思います。まず歌ネットの[利用規約](https://www.uta-net.com/info/kiyaku.html)を確認しましょう！

**ご利用ユーザーの責務及び禁止事項**
以下の行為またはこれに該当する恐れのある行為は一切禁止させていただいております。
１このウェブサイトの全内容又はその一部について、歌ネットに無断で複製、改変、編集、アップロード、提示、送信、頒布、販売など、その他これに類する行為を行う行為
２第三者もしくは歌ネットに不利益または損害を与える行為
３第三者もしくは歌ネットの名誉または信用を毀損する行為
４コンピュータ・ウィルス等を含むソフトウェアまたはプログラムをアップロードする行為
５公序良俗に反する行為
６犯罪行為もしくは犯罪行為に結びつく行為
７法律・法令・条例に違反する行為
８その他、歌ネットが不適切と判断する行為

と記載があります。今回は歌詞データをスクレイピングして、歌詞そのものを表示することが目的では無く、歌詞データを元に対象の歌の歌詞を解析するので問題はなさそうです。

## 実装(Webスクレイピングを利用した形態素分析による可視化)
実装するにあたり、以前学習した参考資料を参考文献に記載しているので、ぜひご覧ください！また、実行はJupyter Notobookで行っています。環境構築に関しては[以前の私の記事](https://qiita.com/seiji1997/items/4bcd6e8a8862de0185f2)を参照してください。今回必要な他のライブラリは別途pipでインストールしているのでpipをググって対応お願いします。

**コード構成**

+ 1, ライブラリのインポート
+ 2, サイトにアクセスし、WEBサイトから情報取得してCSVファイルに出力
+ 3, 歌詞データ（日本語の文章）の抽出
+ 4, 歌詞データ（日本語の文章）を形態素分析
+ 5, 描画

**1, まずはライブラリを一気にインポートします！**

```python
# ライブラリのインストール
# [requests]：webサイトにアクセスして情報を取得できるライブラリ
# [BeautifulSoup]：HTMLの各要素の情報を取得できるライブラリ
import pandas as pd
import requests
from bs4 import BeautifulSoup
import time

# 「Janome」：日本を形態素分析できるライブラリ
# 「WodCloud」：頻出単語の頻度に応じて大きさを調整できるライブラリ
from janome.tokenizer import Tokenizer
from wordcloud import WordCloud
import matplotlib.pyplot as plt 
import matplotlib
from matplotlib.font_manager import FontProperties

# マスク画像を使って表現の幅を広げる
# ImageColorGeneratorとImageを追加でインポート
from wordcloud import WordCloud, ImageColorGenerator
from PIL import Image
import numpy as np
```

**2, ここでWebサイトにアクセスし、WEBサイトから情報取得してCSVファイルに出力を行なっています。**
今回はurlにEXILEさんの歌詞ページをトップページ指定しています。urlのあるwebサイト情報をresponseに代入、さらにHTMLの情報のみをsoupに代入して、td class=’side td1′の情報全てをlinksに代入しています。　

```python
#スクレイピングしたデータを入れるフォーマットを作成
list_df = pd.DataFrame(columns=['曲名','歌詞'])

#歌詞ページのページ数(xページ)に合わせて、xに+1して(0,x+1)
for page in range(0,1): 
    base_url = 'https://www.uta-net.com'

    #歌詞一覧ページを取得
    #複数ページの場合（url = 'https://www.uta-net.com/artist/******/0/' + str(page) + '/'）
    url = 'https://www.uta-net.com/artist/289/' # EXILE
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'lxml')
    links = soup.find_all('td', class_='side td1')
    
    #歌詞情報の取得
    for link in links:
        a = base_url + (link.a.get('href'))
        response = requests.get(a)
        soup = BeautifulSoup(response.text, 'lxml')
        song_name = soup.find('h2').text
        detail = soup.find('p', class_="detail").text
        
        song_kashi = soup.find('div', id="kashi_area")
        song_kashi = song_kashi.text
        song_kashi = song_kashi.replace('\n','')
        song_kashi = song_kashi.replace('この歌詞をマイ歌ネットに登録 >このアーティストをマイ歌ネットに登録 >','　')
        #サーバーに負荷を与えないため1秒待機
        time.sleep(1)
        #取得した歌詞を表に追加
        tmp_se = pd.DataFrame([[song_name], [song_kashi]], index=list_df.columns).T
        list_df = list_df.append(tmp_se)

#csv保存
list_df.to_csv('exile_list.csv', mode = 'w', encoding='utf-8')
```
CSVのデータを読み込み、dfに代入してデータを確認します。

```python
df = pd.read_csv('exile_list.csv')
tiamo =df.loc[101,'歌詞']
```

```python
df.info
```

![スクリーンショット 2022-01-21 12.39.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896292/054f5c67-d7f6-6df1-1f44-2f728429a64d.png)

**3, 歌詞データ（日本語の文章）の抽出**
今回は「Ti Amo」の歌詞を分析するので、「Ti Amo」の歌詞のみをtiamoに代入します。

```python
t = Tokenizer()
tokens = t.tokenize(tiamo)
  
word_list=[]
for token in tokens:
    word = token.surface
    partOfSpeech = token.part_of_speech.split(',')[0]
    partOfSpeech2 = token.part_of_speech.split(',')[1]
     
    if partOfSpeech in['名詞', '動詞', '形容詞', '形容動詞']:
        if (partOfSpeech != "記号"):
            if (partOfSpeech2 != "非自立") and (partOfSpeech2 != "代名詞") and (partOfSpeech2 != "数"):
                word_list.append(word)
 
words=" ".join(word_list)
print(words)  
```
![スクリーンショット 2022-01-21 12.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896292/b055ad02-956d-4747-ed41-f9d60b450ab3.png)

**4, 歌詞データ（日本語の文章）を形態素分析**
私が今回のMacを買うときにUKキーボードを選んだから？なのかわかりませんが、日本語フォントがMacbook内になかったので['./TakaoPGothic.ttf'](https://github.com/byrongibson/fonts/tree/master/backup/truetype.original/takao-gothic)をダウンロードさせていただきました。

```python
font_path = './TakaoPGothic.ttf'  #DLしたパスを指定. /font以下でなくても良い
font_prop = FontProperties(fname=font_path)
```

```python
stop_words = ['し','さ','れ','ない']  # 表示させない単語の設定
fpath = 'TakaoPGothic.ttf'  # 日本語フォント指定
```
**5, 描画**
描画の設定を行います。stop_wordsでは描画させない単語を選定します。あまり意味を持たない単語や、頻出し過ぎている単語がに設定します。描画後にこの言葉はいらないなと思った際に適宜追加します。さらに図の大きさ、背景の色の設定を行なっています。

```python
wordcloud = WordCloud(
    font_path=fpath,
    width=900, height=600,   # default width=400, height=200
    background_color="white",   # default=”black”
    stopwords=set(stop_words),
    max_words=500,   # default=200
    min_font_size=4,   #default=4
    collocations = False   #default = True
    ).generate(words)
```

ここで描画、出力した内容を画像保存しています。

```python
plt.figure(figsize=(15,12))
plt.imshow(wordcloud,interpolation="bilinear")
plt.axis("off")
plt.savefig("tiamo.png")
plt.show()
```

![スクリーンショット 2022-01-21 12.42.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896292/da58e418-9839-635f-e0d2-0d86b457b1d8.png)


##マスク画像を使って表現の幅を広げる

```python
img_color = np.array(Image.open('exile1.png'))
```

ここで画像の色を分析して、抽出します。

```python
wordcloud = WordCloud(
    font_path=fpath,
    width=900, height=600,   # default width=400, height=200
    background_color="white",   # default=”black”
    stopwords=set(stop_words),
    max_words=500,   # default=200
    min_font_size=4,   #default=4
    # mask=img_color　抽出した画像の色を描画の際に活用する設定です。
    mask=img_color,
    collocations = False   #default = True
    ).generate(words)

image_colors = ImageColorGenerator(img_color)
```

mask=img_colorで抽出した画像の形を描画の際に活用する設定を行います。image_colors = ImageColorGenerator(img_color)で抽出した画像の色を描画の際に活用するために色の情報をimage_colorsに代入します。wordcloud.recolor(color_func=image_colors)で描画の色に画像の色を使う設定を行います。

```python
plt.figure(figsize=(15,12))
plt.imshow(wordcloud.recolor(color_func=image_colors),interpolation="bilinear")
plt.axis("off")
plt.savefig("tiamo_mask.png")
plt.show()
```
画像はどっかその辺で拾ってきて、同じディレクトリで管理してください！

![スクリーンショット 2022-01-21 12.58.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896292/15cddafa-dfc9-d51e-b8ac-0a007840be0c.png)

マスク画像の結果はこのようになりました！

![スクリーンショット 2022-01-21 12.58.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896292/462b6637-dda0-6135-00d6-4c43ef3bb921.png)


やはり。Atsushiのところには**愛**が集まってますね！
全体的には**人と愛と想いで満たされたCooooooooooooolな感じ**で終わりました！

#4, 最後に
Webスクレイピングには色々なライブラリもありますし、やり方もあると思います。私は始めたばかりですし、まだまだ知識も不十分だと日々痛感しています。なので、この記事はWebスクレイピングを学ぶきっかけ程度の内容と捉えて、これからも先達たちの素晴らしい記事を読み漁ってください!☜あと、面白いスクレイピングの記事や、良いサイトがあればコメント等でどんどん教えてください！！！ではまた！

#5, 参考文献
1, [スクレイピング・ハッキング・ラボ　Pythonで自動化する未来型生活](https://www.amazon.co.jp/dp/B08H1KBYG2/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
2, [Pythonによるビジネスに役立つWebスクレイピング（BeautifulSoup、Selenium、Requests）](https://www.udemy.com/course/python-web-scraping-with-beautifulsoup-selenium-requests/learn/lecture/20372449?start=0#overview)
3, [スクレイピングは違法？3つの法律問題と対応策を弁護士が5分で解説](https://topcourt-law.com/internet_security/scraping-illegal)
4, [requests](https://docs.python-requests.org/en/latest/)
5, [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)