var reviews = document.querySelectorAll('div[class="d15Mdf bAhLNe"]')
var data = []
reviews.forEach(v => data.push({body: v.outerHTML}))
copy(temp1)
을 하면 클립보드로 데이터가 들어감review-data.json
으로 저장import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import json
import re
from bs4 import BeautifulSoup
import warnings
from konlpy.tag import Twitter
from sklearn.feature_extraction.text import CountVectorizer
warnings.filterwarnings('ignore')
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
df = pd.read_json("review-data.json")
df.head(2)
body | |
---|---|
0 | <div class="d15Mdf bAhLNe"><div class="xKpxId ... |
1 | <div class="d15Mdf bAhLNe"><div class="xKpxId ... |
p = re.compile(r'\d+')
def parser(body):
bs = BeautifulSoup(body, 'html.parser')
user_name = bs.find('span', class_='X43Kjb').text
date = bs.find('span', class_='p2TkOb').text
rating = bs.find('div', {'role':'img'})['aria-label']
rating = p.findall(rating)[-1]
review_text = bs.find('span', {'jsname':'bN97Pc'}).text
return user_name, date, rating, review_text
%%time
df['user_name'], df['date'], df['rating'], df['review_text'] = zip(*df['body'].map(parser))
CPU times: user 4.28 s, sys: 17 ms, total: 4.3 s Wall time: 4.31 s
del df["body"]
df['date'] = pd.to_datetime(df['date'], format='%Y년 %m월 %d일')
df.head(2)
user_name | date | rating | review_text | |
---|---|---|---|---|
0 | Google 사용자 | 2018-08-19 | 5 | 정말 좋아요!! 몇개월 째 잘쓰고있어요ㅎㅎ 한가지 저한테만! 아쉬운 점은 예산 계획... |
1 | Google 사용자 | 2018-08-19 | 2 | 첨엔 좋았는데 쓰다보면 자주 은행 연동 끊기고 오류 나는 거 계속 반복되고 고객센터... |
df = df.sort_values(by='date', ascending=False).reindex()
print("최소 :", min(df['date'].value_counts().index))
print("최대 :", max(df['date'].value_counts().index))
최소 : 2017-12-21 00:00:00 최대 : 2018-08-19 00:00:00
sns.factorplot('rating',kind='count',data=df)
<seaborn.axisgrid.FacetGrid at 0x110035eb8>
df['rating'].value_counts()
5 735 4 385 3 146 1 80 2 54 Name: rating, dtype: int64
low_rate_review = df[df['rating'] <= '3']['review_text']
len(low_rate_review)
280
low_rate_review[:10]
1 첨엔 좋았는데 쓰다보면 자주 은행 연동 끊기고 오류 나는 거 계속 반복되고 고객센터... 78 들어가자 마자 오류떠서 안떠요 73 벌써 3번이나 지문인식이 안먹히네요 인식해도 비밀번호 다시쳐야하고 19 은행 추가해서 관리하다가 카드 추가하면 기존 데이터 다 초기화됩니다. 문의 넣으면 ... 20 신용카드 미분류가 너무 많음. 미분류 건 업체별로 한번 업종 선택하면 다음것도 알아... 80 현대차증권도 추가해 주시면 고맙겠습니다. 66 카뱅은 왜 연동이 안될까요.. 72 증권사 이베스트증권 연동 시도시 앱 다운되네요 67 잘 사용하고있었는데 휴대폰초기화후 재설치했더니 연동오류가자주납니다 34 카카오뱅크는... 추가 안되나요? 카카오뱅크만 써서.......ㅠㅠㅠ Name: review_text, dtype: object
low_rate_review = low_rate_review.apply(lambda x:re.sub('[^가-힣\s\d]',"",x))
low_rate_review[:10]
1 첨엔 좋았는데 쓰다보면 자주 은행 연동 끊기고 오류 나는 거 계속 반복되고 고객센터... 78 들어가자 마자 오류떠서 안떠요 73 벌써 번이나 지문인식이 안먹히네요 인식해도 비밀번호 다시쳐야하고 19 은행 추가해서 관리하다가 카드 추가하면 기존 데이터 다 초기화됩니다 문의 넣으면 친... 20 신용카드 미분류가 너무 많음 미분류 건 업체별로 한번 업종 선택하면 다음것도 알아서... 80 현대차증권도 추가해 주시면 고맙겠습니다 66 카뱅은 왜 연동이 안될까요 72 증권사 이베스트증권 연동 시도시 앱 다운되네요 67 잘 사용하고있었는데 휴대폰초기화후 재설치했더니 연동오류가자주납니다 34 카카오뱅크는 추가 안되나요 카카오뱅크만 써서 Name: review_text, dtype: object
tagger = Twitter()
def get_word(sentence):
nouns = tagger.nouns(sentence)
return [noun for noun in nouns if len(noun) > 1]
cv = CountVectorizer(tokenizer=get_word, max_features=300)
tdf = cv.fit_transform(low_rate_review)
words = cv.get_feature_names()
words[:5]
['가계부', '가나', '가요', '가입', '가장']
count_mat = tdf.sum(axis=0)
count_mat
matrix([[ 16, 1, 16, 11, 4, 7, 4, 4, 4, 6, 2, 8, 2, 3, 27, 19, 2, 4, 2, 2, 3, 34, 3, 3, 4, 8, 2, 7, 4, 5, 11, 9, 2, 2, 2, 4, 3, 2, 6, 2, 22, 2, 2, 9, 16, 2, 2, 25, 2, 2, 2, 9, 10, 2, 5, 7, 5, 3, 15, 7, 3, 3, 2, 2, 2, 5, 3, 2, 7, 2, 3, 3, 6, 2, 2, 9, 3, 6, 3, 2, 6, 2, 2, 4, 3, 4, 87, 4, 2, 3, 2, 2, 2, 3, 15, 3, 3, 3, 15, 7, 2, 8, 2, 16, 2, 3, 14, 2, 7, 2, 2, 11, 2, 2, 4, 4, 2, 4, 2, 11, 9, 2, 6, 2, 2, 2, 2, 2, 2, 2, 3, 2, 12, 2, 2, 5, 13, 6, 2, 2, 6, 3, 32, 6, 3, 23, 5, 3, 2, 15, 120, 2, 4, 2, 57, 2, 2, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 31, 1, 2, 2, 1, 2, 2, 2, 3, 2, 2, 9, 4, 2, 6, 1, 23, 37, 1, 3, 3, 2, 1, 1, 2, 1, 6, 1, 3, 2, 10, 9, 12, 7, 3, 3, 11, 2, 2, 2, 3, 2, 3, 7, 10, 2, 2, 4, 5, 5, 2, 2, 3, 2, 2, 7, 3, 9, 2, 3, 2, 2, 32, 5, 10, 9, 2, 5, 6, 3, 2, 3, 12, 4, 2, 4, 39, 11, 83, 2, 2, 2, 3, 3, 2, 4, 2, 4, 2, 3, 4, 2, 2, 4, 2, 3, 10, 1, 1, 2, 1, 2, 12, 1, 2, 1, 1, 1, 4, 3, 3, 5, 2, 2, 8, 4, 3, 1, 2, 4, 3, 1, 1, 8, 16, 1, 1, 5, 6]], dtype=int64)
count = np.squeeze(np.asarray(count_mat))
word_count = list(zip(words, count))
word_count = sorted(word_count, key=lambda t:t[1], reverse=True)
word_count[:15]
[('연동', 120), ('뱅크', 87), ('카카오', 83), ('오류', 57), ('카드', 39), ('인증서', 37), ('공인', 34), ('어플', 32), ('지출', 32), ('은행', 31), ('계속', 27), ('다시', 25), ('업데이트', 23), ('인증', 23), ('너무', 22)]