forked from loisRK/gp_team
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCrawling_for_CSV.py
323 lines (247 loc) · 11.9 KB
/
Crawling_for_CSV.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# (selenium)
import re
from selenium import webdriver
import time
# (BeautifulSoup)
from bs4 import BeautifulSoup
# (DataFrame)
import pandas as pd
from datetime import datetime
from sentiment_model import Sentiment
class Find_Store():
def __init__(self):
super().__init__()
self.Positive_Review = None # 모델학습결과 넣을 변수
self.Negative_Review = None # 모델학습결과 넣을 변수
def play(self, sname):
global store_total_list
global star_total_list
global review_total_list
global review_list
global star_list
global menu_list
global star_opt
global Star_Total
global Comment_Total
global date_list
# 크롤링 작업
Store_link = "https://www.yogiyo.co.kr/mobile/#/"
driver = webdriver.Chrome("chromedriver.exe")
driver.get(url=Store_link)
time.sleep(3)
driver.find_element_by_xpath('//*[@id="button_search_address"]/button[2]').click()
time.sleep(3)
driver.find_element_by_xpath('//*[@id="category"]/ul/li[1]/a').click()
time.sleep(3)
# 검색버튼 클릭 후 입력받은 가게명 검색창에 입력
driver.find_element_by_xpath('//*[@id="category"]/ul/li[15]/form/div/input').click()
time.sleep(3)
driver.find_element_by_xpath('//*[@id="category"]/ul/li[15]/form/div/input').send_keys(sname)
# search 버튼 클릭
driver.find_element_by_xpath('//*[@id="category_search_button"]').click()
time.sleep(3)
# 가게 여부를 확인해주는 변수 check_store
check_store = driver.find_element_by_xpath('//*[@id="content"]/div/div[7]').text == ''
# test-----------------------------------------------------------------------------------------
if check_store == False:
print('가게가 없을 경우')
driver.quit()
elif check_store == True:
print("가게가 있을 경우")
# --------------------------------------------------------------------------------------------
# 첫번째 가게 클릭
driver.find_element_by_xpath(
'//*[@id="content"]/div/div[5]/div/div/div[1]/div/table/tbody/tr/td[2]/div/div[1]').click()
# 푸라닭만 1000플 긁어오느라 추가한 코드
# driver.find_element_by_xpath('//*[@id="content"]/div/div[5]/div/div/div[2]/div').click()
time.sleep(3)
# 클린댓글 클릭
driver.find_element_by_xpath('//*[@id="content"]/div[2]/div[1]/ul/li[2]/a').click()
time.sleep(3)
# 가게 정보 긁어오기
self.Star_Total = driver.find_element_by_xpath(
'//*[@id="content"]/div[2]/div[1]/div[5]/div[1]/div/div/strong').text
self.Comment_Total = driver.find_element_by_xpath('//*[@id="content"]/div[2]/div[1]/ul/li[2]/a/span').text
print("더보기란 클릭 시작")
# 여기서 수정한 if문 넣기------------------------------------------------------------------------------------------
# 댓글의 인덱싱은 xpath의 경로 중 li[]에서 [] 안에 있는 숫자로 결정됨
# 시작 인덱싱은 2부터 시작
# 한번에 보여줄 수 있는 댓글의 갯수는 10개이며 넘어갈 경우 더보기란 생성
# 더보기를 누를 때마다 보여지는 댓글이 10개씩 추가됨
# 댓글의 갯수가 x라는 변수로 지정하였을 때 더보기 버튼의 총 갯수는 x/10
reviewtotal = int(self.Comment_Total)
origin_more_click_count = (reviewtotal / 10) - 1
# 원하는 댓글의 수를 입력하면 그 갯수에 맞춰 더보기를 클릭할 수 있도록 설정하기(지금은 임의로 30개를 긁어올 수 있도록 2으로 설정)
# 2 대신 넣어야 하는 것(입력값의 변수 = x) => x/10 - 1
# more_click_count = 2
# more_click_count = (1100 / 10) - 1 # 댓글 1000개로 고정
more_click_count = origin_more_click_count
if reviewtotal < 11:
driver.quit()
print("댓글이 없거나 너무 적습니다.")
elif reviewtotal > 10: # 이 때부터 더보기란 생성
for i in range(1, int(more_click_count) + 1):
driver.find_element_by_xpath(f'//*[@id="review"]/li[{(i * 10) + 2}]/a').click()
time.sleep(2)
# return print("Success") # for문에서 나올 때 오류가 발생하며 비정상종료됐지만 return 값이 생기니깐 비정상 종료는 안됨
# return을 사용하면 종료가 되는 것이기 때문에 결국 원점
if i == int(more_click_count):
break # break로 해결됨
elif i < int(more_click_count):
continue
# print('TEEEEEST') # 하지만 이후 실행되야할 명령어들이 실행되지 않고 끝이 남
break
print('더보기란 클릭 완료')
# --------------------------------------------------------------------------------------------------------------
# html 긁어오기 전 충분히 로딩할 시간 부여
time.sleep(60)
# selenium 작업으로 더보기 펼친 후 html 긁어오기
html = driver.page_source
print('html')
# print(html)
time.sleep(3)
soup = BeautifulSoup(html, 'html.parser')
# id=review 인 ul 태그 가져오기
time.sleep(3)
review_tag = soup.select_one("ul.list-group.review-list")
# print(review_tag)
review_list = []
menu_list = []
star_list = []
star_opt = []
date_list = []
time.sleep(3)
# 리뷰 review
# ul tag 중 원하는 tag 가져오기
for p in review_tag.find_all("p", class_="ng-binding", attrs={"ng-show": "review.comment"}):
review_list.append(p.get_text())
print(len(review_list))
print(review_list)
time.sleep(3)
# 리뷰 메뉴
for div in review_tag.select('div.order-items.default.ng-binding'):
menu_list.append(div.get_text())
print(len(menu_list))
print(menu_list)
time.sleep(3)
# 리뷰 total star
for s in review_tag.select('div.star-point > span.total'):
star = ""
for st in s.select('span.full.ng-scope'):
star += st.get_text()
star_list.append(star)
print(len(star_list))
print(star_list)
time.sleep(3)
# 리뷰 품목별 star
for s in review_tag.select('div.star-point > span.category'):
star_opt.append(s.get_text())
print(len(star_opt))
print(star_opt)
time.sleep(3)
print('check')
# 리뷰 날짜
for s in review_tag.select('span.review-time.ng-binding'):
s1 = s.get_text()
s2 = s1.split(' ')
if len(s2) == 3:
s3 = s2[0] + ' ' + s2[1]
date_list.append(s3)
print(len(date_list))
print(date_list)
time.sleep(3)
# 크롤링 완---------------------------------------------------------------------------------------------------------
global review_df
global menu_df
global star_df
global staropt_df
global date_df
# review_df 만들기
review_df = pd.DataFrame({"review":review_list}, index=None)
print(review_df)
print('review success')
time.sleep(3)
# menu_df 만들기
menulist = []
for m1 in menu_list:
if m1 == '\n':
continue
m1 = m1.replace('\n', '').strip()
menulist.append(m1)
menu_df = pd.DataFrame({'Menu': menulist}, index=None)
print(menu_df)
print('menu success')
time.sleep(3)
# star_df 만들기
star_df = pd.DataFrame({"Total Star":star_list}, index=None)
print(star_df)
print('star success')
time.sleep(3)
# staropt_df 만들기
staropt_df = pd.DataFrame({'Star_opt':star_opt}, index=None)
print(staropt_df)
print('star_opt success')
time.sleep(3)
# date_df 만들기
date_df = pd.DataFrame({'Date':date_list}, index=None)
print('date success')
time.sleep(3)
# 데이터 프레임 합치기
Review_info_df = pd.concat([review_df, star_df, menu_df, staropt_df, date_df], axis=1)
print('Merge success')
time.sleep(3)
# 고객이 남긴 데이터들이 담겨있는 데이터프레임 원본을 csv파일로 변환
Review_info_df.to_csv(f'Original_{sname}.csv')
time.sleep(3)
# 원하는 기간의 데이터 추출 ----------------------------------------------------------------------------------------
# 원하는 기간을 최근 1년으로 정함
# from datetime import datetime 필요
d_list = []
now_year = datetime.today().year
now_month = datetime.today().month
for d in range(now_month, 13):
d_list.append(str(now_year - 1) + '년 ' + str(d) + '월')
for d in range(1, now_month):
d_list.append(str(now_year) + '년 ' + str(d) + '월')
print(d_list)
Before_Review_df = Review_info_df[Review_info_df['Date'].isin(d_list)]
print('final success')
time.sleep(3)
# --------------------------------------------------------------------------------------------------------------
# 이모지로만 된 댓글 삭제-------------------------------------------------------------------------------------------
hangul = re.compile('[^ ㄱ-ㅣ가-힣]+')
Before_Review_df["review"] = Before_Review_df["review"].apply(lambda x: hangul.sub('', x))
time.sleep(3)
Before_Review_df.drop(Before_Review_df[Before_Review_df['review'] == ''].index, inplace=True)
time.sleep(3)
# --------------------------------------------------------------------------------------------------------------
# print(Before_Review_df)
print('###INFO###')
print(Before_Review_df.info())
# 최근 1년간의 데이터들이 담긴 Review 데이터 프레임을 csv변환
Before_Review_df.to_csv(f'Before_{sname}.csv')
print(Before_Review_df.tail())
# 예측 점수 컬럼이 포함된 최종 리뷰 데이터프레임 만들기------------------------------------------------------------------
After_Review_df = Before_Review_df
# 모델 실행
from sentence_transformers import SentenceTransformer
from keras.models import load_model
import numpy as np
model = SentenceTransformer('jhgan/ko-sroberta-multitask')
df_em = pd.DataFrame({'word': After_Review_df["review"],
'embedding': pd.Series([] * len(After_Review_df["review"]))})
df_em['embedding'] = df_em['word'].map(lambda x: list(model.encode(x)))
model = load_model('./review_predict.h5')
feature = np.vstack(df_em.embedding.values)
print("Model predicting...")
predict_score = model.predict(feature)
output = [x + 1 for x in map(np.argmax, predict_score)]
print("********** 모델 결과 ***********")
print(output)
print("*******************************")
output_df = pd.DataFrame({'Output': output}, index=None)
After_Review_df = pd.concat([After_Review_df, output_df], axis=1)
After_Review_df = After_Review_df.dropna()
print(After_Review_df.head)
After_Review_df.to_csv(f'After_{sname}_total.csv')
print('★☆Finish☆★')