####星野源さんの歌詞はどういった単語が多く使われているのかを調べるために、Webスクレイピングを行った。
Webスクレイピングは、Webサイトから情報を抽出する技術のこと。
*ウェブサイトによってスクレイピングを拒否している場合があり、そういったサイトにスクレイピングを行うと処罰の対象となるため注意!アクセスしすぎも迷惑をかけるのでダメ!
##今回の目標
Webスクレイピングで、星野源さん全曲の歌詞を取得し、シルエットに使用頻度の高い単語を当てはめる。
####顔の輪郭では分からないかもしれないが、星野源さん
##参考サイト
米津玄師の歌詞をWordCloudで可視化してみた。(Qiita)
####かなり参考にさせてもらいました。
##ソースコードと雑談
昨年春に大学の先輩から作ってみればと言われた。
当時はPythonに初めて触れたので、見よう見まねで作成した。
1年経ってから備忘録を書くというなんともマヌケなものだが、折角の成果だから載せておく。
###1.サイトから星野源作詞・作曲の曲を全て抜き出す
import os
import re
import bs4
import time
import requests
import pprint
def load(url):
res = requests.get(url)
res.raise_for_status()
return res.text
def pickup_tag(html, find_tag):
soup = bs4.BeautifulSoup(str(html), 'html.parser')
paragraphs = soup.find_all(find_tag)
return paragraphs
def parse(html):
soup = bs4.BeautifulSoup(str(html), 'html.parser')
# htmlタグの排除
kashi_row = soup.getText()
kashi_row = kashi_row.replace('\n', '')
kashi_row = kashi_row.replace(' ', '')
# 英数字の排除
kashi_row = re.sub(r'[a-zA-Z0-9]', '', kashi_row)
# 記号の排除
kashi_row = re.sub(r'[ <>♪`‘’“”・…_!?!-/:-@[-`{-~]', '', kashi_row)
# 注意書きの排除
kashi = re.sub(r'注意:.+', '', kashi_row)
return kashi
def main():
with open('hosino_kashi.txt', 'a') as f:
# アーティストページのアドレス
url = f'https://www.uta-net.com/artist/9867/'
# 曲ページの先頭アドレス
base_url = f'https://www.uta-net.com'
# ページの取得
html = load(url)
# 曲ごとのurlを格納
musics_url = []
# 歌詞を格納
kashis = ''
""" 曲のurlを取得 """
# td要素の取り出し
for td in pickup_tag(html, 'td'):
# a要素の取り出し
for a in pickup_tag(td, 'a'):
# href属性にsongを含むか
if 'song' in a.get('href'):
# urlを配列に追加
musics_url.append(base_url + a.get('href'))
""" 歌詞の取得 """
for i, page in enumerate(musics_url):
print('{}曲目:{}'.format(i + 1, page))
html = load(page)
for div in pickup_tag(html, 'div'):
# id検索がうまく行えなかった為、一度strにキャスト
div = str(div)
# 歌詞が格納されているdiv要素か
if r'itemprop="text"' in div:
# 不要なデータを取り除く
kashi = parse(div)
print(kashi, end = '\n\n')
# 歌詞を1つにまとめる
kashis += kashi + '\n'
# 1秒待機
time.sleep(1)
break
# 歌詞の書き込み
f.write(kashis)
if __name__ == '__main__':
main()
###2. WordCloudを使用して、出てくる回数の多い単語を大きくして表示
import MeCab
from matplotlib import pyplot as plt
from wordcloud import WordCloud
# テキストファイル読み込み
with open('hoshino_kashi.txt', mode='rt', encoding='utf-8') as fi:
source_text = fi.read()
# MeCabの準備
tagger = MeCab.Tagger()
tagger.parse('')
node = tagger.parseToNode(source_text)
# 名詞を取り出す
word_list = []
while node:
word_type = node.feature.split(',')[0]
if word_type == '名詞':
word_list.append(node.surface)
node = node.next
# リストを文字列に変換
word_chain = ' '.join(word_list)
#無意味そうな単語除去
stop_words = ['そう', 'よう', 'もの', 'こと', 'まま']
# ワードクラウド作成
W = WordCloud(font_path='/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc',
width=640, height=480,
background_color='white',
colormap='bone',
stopwords=set(stop_words)).generate(word_chain)
plt.imshow(W)
plt.axis('off')
plt.show()
ここまできたら、四角よりもシルエットに単語を並べた方が良いかなと思い・・・。
###写真からシルエットを出す方法を忘れた
###3.写真から顔面が青白い星野源さんを作成
####OpenCVを用いた画像処理を施し、写真を青白くさせる。ここの調整が難しかった。
青白くならないと、綺麗なシルエットが出ない。
写真は肖像権に引っかかるかもしれないので、一応載せない。
(すみません・・・)
上半身がしっかり写っているものが良いと思われる。
import cv2
import numpy as np
import matplotlib.pyplot as plt
BLUR = 21
CANNY_THRESH_1 = 10
CANNY_THRESH_2 = 100
MASK_DILATE_ITER = 10
MASK_ERODE_ITER = 10
MASK_COLOR = (1.0,0.0,0.0)
img = cv2.imread('hoshino2.jpg') #青白くしたい画像
img1 = img[0 : 2100, 0: 2650]
gray = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2)
edges = cv2.dilate(edges, None)
edges = cv2.erode(edges, None)
contour_info = []
contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
for c in contours:
contour_info.append((
c,
cv2.isContourConvex(c),
cv2.contourArea(c),
))
contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True)
max_contour = contour_info[0]
mask = np.zeros(edges.shape)
cv2.fillConvexPoly(mask, max_contour[0], (255))
mask = cv2.dilate(mask, None, iterations=MASK_DILATE_ITER)
mask = cv2.erode(mask, None, iterations=MASK_ERODE_ITER)
mask = cv2.GaussianBlur(mask, (BLUR, BLUR), 0)
mask_stack = np.dstack([mask]*3)
mask_stack = mask_stack.astype('float32') / 255.0
img1 = img1.astype('float32') / 255.0
masked = (mask_stack * img1) + ((1-mask_stack) * MASK_COLOR)
masked = (masked*255).astype('uint8')
plt.imshow(img_a)
plt.axis("off")
plt.show()
####スクリプトにコメントが無くてごめんなさい
####そのうち書きます。
###4.顔面が青白い星野源さんにWordCloudを適用
from PIL import Image
import numpy as np
import MeCab
from matplotlib import pyplot as plt
from wordcloud import WordCloud
# テキストファイル読み込み
with open('hoshino_kashi.txt', mode='rt', encoding='utf-8') as fi:
source_text = fi.read()
# MeCabの準備
tagger = MeCab.Tagger()
tagger.parse('')
node = tagger.parseToNode(source_text)
# 名詞を取り出す
word_list = []
while node:
word_type = node.feature.split(',')[0]
if word_type == '名詞':
word_list.append(node.surface)
node = node.next
# リストを文字列に変換
word_chain = ' '.join(word_list)
#無意味そうな単語除去
stop_words = ['そう', 'よう', 'もの', 'こと', 'まま', 'これ', 'それ']
def get_wordcrowd_mask( word_chain, imgpath ):
img_color = np.array(Image.open( imgpath ))
wc = WordCloud(font_path='/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc',
mask=img_color,
collocations=False, # 単語の重複しないように
stopwords=set(stop_words),
background_color='white',
contour_width=3,
contour_color='black'
).generate( word_chain )
# show
plt.figure(figsize=(6,6), dpi=200, facecolor='white')
plt.imshow(wc)
plt.axis("off")
plt.show()
####顔面が青白いとWordCloudを適用した際に、顔の輪郭がしっかり出る
####星野源さんの曲は、日常や身近な人を歌っていることが多いのかなと思う。