지난 게시글에서는 한 가게에 유저들이 남긴 리뷰를 모으는 코드를 살펴보았는데요.
이번 게시글에서는 한 유저의 프로필에 접속하여
해당 유저가 여러 가게에 남긴 리뷰들을 모두 모으는 코드를 살펴보겠습니다.
이전 코드를 참고하여 코드를 작성했으니 이해가 안 된다면 지난 게시글부터 읽어주세요!
https://ssseoyneee.tistory.com/3
Python | 웹 크롤링 | 네이버 플레이스 리뷰 크롤링 (1)
맛집 추천시스템을 위한 프로젝트를 진행하며추천을 위해 필요한 정보를 네이버 지도로부터 얻고자 했습니다.아래 블로그의 코드를 참고했고, 지피티가 정말 많은 것을 도와줬습니다 :) https://
ssseoyneee.tistory.com
환경 세팅하기
지난 게시글에서 수집한 데이터를 바탕으로 크롤링을 진행합니다.
url 열에 있던 유저 프로필 url에 접속하여 해당 유저가 남긴 리뷰를 받아옵니다.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import pandas as pd
from openpyxl import Workbook
import time
import os
import re
P_names = [
"만나계 선유도점","온수반 선유도점","너도나도식당 선유도본점","삼산회관 선유도역점","뭉텅 선유도점","동양솥밥 선유도점", "지즐 한우오마카세 선유도역점",
"오보타르트 선유도역 본점", "멕시코식당 선유도역", "종로계림닭도리탕원조 선유도점", "김정육 선유도역본점", "아덴블랑제리 선유도역점", "멕시코식당 선유도역",
"돼지대첩 영등포 선유도역점", "스위트1225 선유도역점", "이남장 선유도점", "핵밥 선유도점", "양평의양", "선유슬로우", "서울미트볼 선유도역점",
"미태리 선유도점", "돈카츠식탁 선유도역점", "마이요거트립 선유도점", "월남선생 선유도역점", "바빈스커피 선유도역점", "아리스타커피 선유도점",
"핀즈 선유도점", "커피베이 선유도점", "전설의왕만두 선유도역점", "얌샘김밥 선유도점", "양평의양", "철이네", "홍두깨본칼국수", "마콘", "코지로",
"스페셜티 스튜디오", "민코", "베이커리 손유", "23평", "레이지아웃", "스낵바 아타시 당산역본점", "선유이층", "공간다반사", "선유나루", "소복소복",
"선유수제맥주", "선유슬로우", "고양이가밟은쿠키", "베이커리산", "카레모토", "선유양꼬치", "로너클럽", "더블플랫", "이순", "ToTo1001",
"루나제이커피", "카쿠스시", "한신우동 당산점", "마콘", "선유슬로우", "당산끝집", "참새방앗간", "계탄몽", "다래칼국수", "경아식당 당산점",
"논키", "이자카야 베이비", "고양진김치찌개 당산직영점", "피크닉앤", "코지로 당산역점", "선유골목집", "반카페", "코하루", "디데이원", "명동칼국수 선유점",
"야키토리 베이비", "싱싱해포차", "my own garden", "당산계단집", "청록미나리식당 당산점", "당산진미관", "브라이트사이즈", "옥된장 당산점", "카페설리번 당산점",
"더스티", "서울객점 당산양평점", "연참치", "카페 이파네마", "바지락칼국수&아구찜,보쌈", "후무", "퍼스트커피랩 당산역점", "말론하우스", "당산항",
"전주이모네식당", "안단단", "파니피카", "커피101스트릿 당산점", "스쿱앤그릭", "노버든", "브링미커피 브루어스", "우리쌀빵", "아키비스트 서울양평점", "플레블리 떡케이크",
"웨이프", "한숲", "밀로브레드", "헬로앨리스마켓24선유점", "예일타운 커피랩", "브런치빈 당산점", "치키차카초코 영등포점", "카페 오밀리우",
"호두붐 당산점", "진켈란젤로 치즈케이크", "흘러", "모닝캄커피랩 당산점", "초가오 영등포점", "오가다 영등포직영점", "쉬즈베이글 당산점", "만랩커피 당산중앙점",
"곳온니플레이스 OLD STREET", "코지로", "철이네", "23평", "일성옥", "바지락칼국수&아구찜,보쌈", "소백탄", "소공원", "월양", "내리다곰",
"쌀통닭 당산역점", "단토리 당산역점", "돈랩", "업스테어앤드", "당산 3.5 왕소금구이", "청춘냉동삼겹살", "호랭이반점 당산역점", "선유가츠",
"모어베지샐러드", "고흥수산"]
etc = ['오락시설', '한약국,한약방', '국토교통부', '영화관', '화장품,향수',
'문구,팬시용품', '네일아트,네일샵', '관리,안내', '침구,커튼',
'마사지, 지압', '체험여행', '특산물,관광민예품', '남성정장',
'고속도로휴게소', '웨딩컨설팅,플래너', '슈퍼,마트', '종합생활용품',
'기업', '공영주차장', '다이어트,비만', '주차장', '공방', '피부과',
'약국', '귀금속,시계', '가구', '폐업했거나 정보 제공이 중지된 장소',
'속눈썹증모,연장', '박물관', '성형외과', '스포츠용품', '화물운송',
'S', '안경원', '치과', '없음', '건강기능보조식품', '결혼예물', '애견용품',
'셀프,대여스튜디오', '동물병원', '드럭스토어', '왁싱,제모', '호텔', '종합패션',
'미용실', '공사,공단', '헬스장', '내과', '편의점', '미술관', '슈퍼,마트',
'GS칼텍스주유소', '전기,가스,수도사업', 'HD현대오일뱅크주유소', '약국',
'영화관', '종합가전', 'SK주유소', '고속도로휴게소', '종합생활용품',
'소프트웨어개발', '관람,체험', '유아,아동용품', '솔루션개발', '정장',
'남성의류', '신발', '유아동복', '상가,아케이드', '편의점', '화장실',
'S', '내과', '가방,핸드백', '등산,아웃도어', '카드단말기', '렌터카', '패션',
'절,사찰', '은행', '캐주얼웨어', '스포츠용품', '주차장', '판촉,기념품',
'문화센터', '장례식장', '문구,팬시용품', '호텔', '안경원', '여성의류',
'드럭스토어', '서점', '주유소', '민간자동차검사소', '산업용품', '치과',
'현금인출기', '갤러리,화랑', '도장', '미용실', '공영주차장', '전문건설업',
'국토교통부', '특산물,관광민예품', '타이어,휠', '국제,항공화물', '휴대폰수리',
'기업', '관리,안내', '정형외과', '도보코스', '콘도,리조트', '해수욕장,해변',
'온천,스파', '기부,모금단체', '자연,생태공원', '세탁', '우편취급소', '차',
'노래방', '세탁소', '전망대', '회관', '한의원', '패션잡화', '의류제작',
'조명,디스플레이', '명절 무료 개방 주차장', '신용조합', '산부인과',
'병원,의원', '콘택트렌즈전문', '정육점', '교습학원,교습소', '컨벤션센터',
'당구장']
options = Options()
options.add_argument("window-size=1920x1080")
service = Service(executable_path=ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=options)
user_URL_list = []
file_path = 'c:\\Users\\kimsy\\Desktop\\Filtered_Review_Sup.xlsx'
sheet_name = 'Sheet1' # 엑셀 파일의 경로
# 엑셀 파일을 읽습니다.
df = pd.read_excel(file_path, sheet_name = sheet_name)
start_name = "de****"
start_index = df[df.iloc[:, 1] == start_name].index[0]
# start_index 이후의 데이터를 가져옵니다.
User_data = df.iloc[start_index:, [0, 1, 7, 8]].values.tolist()
xlsx = Workbook()
file_name = f'Reviewer.xlsx'
list_sheet = xlsx.create_sheet('output')
list_sheet.append(['nickname', 'name','category', 'review', 'date', 'tags', 'numbers', 'OX'])
P_names는 타깃으로 설정한 지역의 가게를 담은 리스트이고,
etc는 요식업 외의 업종에 리뷰를 남긴 경우 리뷰를 받아오지 않기 위해 작성한 리스트입니다.
리뷰를 받으면서 새로운 업종을 etc 리스트에 업데이트했습니다.
이전 게시글과 마찬가지로 라이브러리를 불러오고 WebDriver 설정을 해줍니다.
df에 전에 받은 엑셀 파일을 불러오고 그 중 Name(가게 이름), nickname(유저 이름), url(유저 프로필 url), 9th_column(가게가 초기 타깃 가게에 해당하는지 여부) 총 네 개의 열을 뽑아 User_data라는 새로운 데이터프레임을 만듭니다.
새로운 리뷰 데이터가 담길 파일은 'Reviewer.xlsx'로 설정했고, 해당 파일의 'output' 시트에
유저 이름, 가게 이름, 가게 카테고리, 리뷰 내용, 방문 날짜, 리뷰 태그, 재방문 횟수, 초기 타겟 여부를 모을 계획입니다.
current_user_name = None
for u in User_data:
start_time = time.time()
user_origin = u[0].split('\n')[0]
user_nickname = u[1].split('\n')[0]
user_URL = u[2]
#user_visited = [item.strip() for item in u[3].split(', ')]
#user_visited.append(user_origin)
#print(user_visited)
current_user_name = user_nickname
driver.get(user_URL)
driver.implicitly_wait(5)
user_URL_list.append(user_URL)
User_data에 있는 데이터에 대해 user_origin, user_nickname, user_URL 등을 정의합니다.
user_URL에 접속하는 코드를 작성합니다.
사진/영상 리뷰만 체크박스 해제하기
유저 프로필에 접속했을 때 초기 화면은 왼쪽인데요.
보시는 것처럼 '사진/영상 리뷰만'에 체크되어 있기 때문에 사진/영상을 포함한 리뷰만 로드됩니다.
이때 사진/영상이 없는 리뷰도 모을 계획이기 때문에 해당 체크박스를 해제해야 하는데요.
photo_video_review_checkbox = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, 'onlyHasMedia')))
# 체크되어 있다면 클릭해서 해제
if photo_video_review_checkbox.is_selected():
driver.execute_script("arguments[0].click();", photo_video_review_checkbox)
time.sleep(2) # 잠시 대기하여 상태가 반영되도록 함
first_post = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button._5RYLm7.bEchjN')))
driver.execute_script("arguments[0].click();", first_post)
time.sleep(5)
photo_video_review_checkbox라는 변수를 만들고, 체크되어 있는 상태라면 클릭해서 해제하는 코드를 써줍니다.
이렇게 체크박스가 해제된 후에는 첫 번째 리뷰를 클릭해 리뷰 상세 페이지로 들어갑니다.
리뷰 상세 페이지에 들어간 후에는 스크롤로 모든 리뷰를 로드할 수 있기 때문에 해당 액션은 한 번만 해주면 됩니다.
자동 스크롤 작동시키고 데이터 파싱하기
가게 리뷰 페이지와 가장 큰 차이점은 리뷰를 불러오기 위해 더보기 버튼을 따로 눌러주지 않아도 된다는 것인데요.
스크롤을 아래로 내리면 자동으로 로딩되는 형태입니다.
따라서 아래와 같이 PAGE_DOWN을 작동시켜 줍니다.
for i in range(0,40):
for c in range(0,30):
driver.find_element(By.TAG_NAME, 'body').send_keys(Keys.PAGE_DOWN)
time.sleep(1)
try:
nickname = driver.find_element(By.CSS_SELECTOR, 'h1._3q8NFd').text.strip()
if nickname != user_nickname:
print("Something goes wrong!!! You should do it more better..!")
stores = driver.find_elements(By.CSS_SELECTOR, 'div._898uc8')
y = 0
for s in stores:
i_store_review = s.find_elements(By.CSS_SELECTOR, 'div.pui__vn15t2')
if i_store_review and not i_store_review[0].text.strip():
store_review = "없음"
else:
store_review = s.find_element(By.CSS_SELECTOR, 'div.pui__vn15t2').text.strip()
if store_review != "없음":
store_name = s.find_element(By.CSS_SELECTOR, 'span.pui__pv1E2a').text.strip()
i_store_category = s.find_elements(By.CSS_SELECTOR, 'div.pui__Vb-OW1')
if i_store_category and not i_store_category[0].text.strip():
store_category = "없음"
elif any("폐업" in element.text for element in i_store_category):
store_category = "폐업했거나 정보 제공이 중지된 장소"
else:
store_category = s.find_element(By.CSS_SELECTOR, 'span.pui__WUm6H8').text.strip()
if store_category not in etc: # 요식업 카테고리에 해당하는 경우
# 방문일\n7.28.일\n년 7월 28일 일요일 으로 뜨는 것을 수정해야함
i_store_date = s.find_element(By.CSS_SELECTOR, 'span.pui__gfuUIT').text.strip()
line = i_store_date.split('\n')
store_date = line[-2]
revisit_elements = s.find_elements(By.CSS_SELECTOR, 'span.pui__gfuUIT')
revisit = revisit_elements[1].text.strip() if len(revisit_elements) > 1 else ''
# revisit "번째 방문" 문자 제거
if revisit:
revisit = int(revisit[:-5])
# 태그 더보기 클릭 후 리뷰 태그 수집
i_tags = [tag.text.strip() for tag in s.find_elements(By.CSS_SELECTOR, 'div.pui__HLNvmI')]
i_tags = str(i_tags)
if "+" not in i_tags:
i_tag = [tag.text.strip() for tag in s.find_elements(By.CSS_SELECTOR, 'div.pui__HLNvmI span.pui__jhpEyP')]
else:
tag_button = s.find_element(By.CSS_SELECTOR, 'a.pui__jhpEyP.pui__ggzZJ8')
driver.execute_script("arguments[0].click();", tag_button)
time.sleep(1)
i_tag = [tag.text.strip() for tag in s.find_elements(By.CSS_SELECTOR, 'div.pui__HLNvmI span.pui__jhpEyP')]
# 초기 타깃 가게에 해당하는지 여부 수집
for v in P_names:
if str(store_name) != str(v):
OX = "X"
else:
OX = "O"
break
# 파일에 저장
list_sheet.append([nickname, store_name, store_category, store_review, store_date, ", ".join(i_tag), revisit , OX])
y = y+1
xlsx.save(file_name)
end_time = time.time()
elapsed_time = int(end_time - start_time)
print(f"Data collection completed and saved to Excel. number = {y}, (time = {elapsed_time})")
if elapsed_time < 200 and y < 150:
print(f"이름: {user_nickname}, 시간:{elapsed_time}, 횟수:{y}, 마지막 날짜:{store_date}")
except Exception as e:
print('Error:', e)
print(f"Data collection completed up to place: {current_user_name}. Data saved to Excel.")
# Excel 파일 저장 및 드라이버 종료
xlsx.save(file_name)
driver.quit()
print("Data collection completed and saved to Excel.")
이전과 같은 방식으로 가게와 유저에 대한 정보를 수집합니다.
이때 리뷰 내용이 있는 경우에만 리뷰를 수집하며,
가게 카테고리가 없거나 폐업, 정보 제공이 중지된 장소인 경우
store_category에 "없음" 혹은 "폐업했거나 정보 제공이 중지된 장소"를 입력합니다.
데이터를 모으는 속도를 높이기 위해 가게 카테고리가 etc 리스트에 해당하지 않는,
즉 요식업에 해당한다고 볼 수 있는 가게에 대한 리뷰만 다음의 액션을 취합니다.
1. 방문일 데이터 형식 수정
2. revisit 열의 "번째 방문" 텍스트 삭제
3. 태그 더보기 클릭 후 리뷰 태그 수집
4. 초기 타깃 여부 체크
5. 모은 정보를 파일에 저장
elapsed_time과 y를 받은 이유는 너무 적은 시간동안 너무 적은 수의 리뷰를 수집한 경우를 체크하여
추후 다시 데이터를 수집하기 위함입니다.
코드를 돌려보면 결과가 엑셀 파일에 잘 저장됩니다!
전체 코드
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import pandas as pd
from openpyxl import Workbook
import time
import os
import re
P_names = [
"만나계 선유도점","온수반 선유도점","너도나도식당 선유도본점","삼산회관 선유도역점","뭉텅 선유도점","동양솥밥 선유도점", "지즐 한우오마카세 선유도역점",
"오보타르트 선유도역 본점", "멕시코식당 선유도역", "종로계림닭도리탕원조 선유도점", "김정육 선유도역본점", "아덴블랑제리 선유도역점", "멕시코식당 선유도역",
"돼지대첩 영등포 선유도역점", "스위트1225 선유도역점", "이남장 선유도점", "핵밥 선유도점", "양평의양", "선유슬로우", "서울미트볼 선유도역점",
"미태리 선유도점", "돈카츠식탁 선유도역점", "마이요거트립 선유도점", "월남선생 선유도역점", "바빈스커피 선유도역점", "아리스타커피 선유도점",
"핀즈 선유도점", "커피베이 선유도점", "전설의왕만두 선유도역점", "얌샘김밥 선유도점", "양평의양", "철이네", "홍두깨본칼국수", "마콘", "코지로",
"스페셜티 스튜디오", "민코", "베이커리 손유", "23평", "레이지아웃", "스낵바 아타시 당산역본점", "선유이층", "공간다반사", "선유나루", "소복소복",
"선유수제맥주", "선유슬로우", "고양이가밟은쿠키", "베이커리산", "카레모토", "선유양꼬치", "로너클럽", "더블플랫", "이순", "ToTo1001",
"루나제이커피", "카쿠스시", "한신우동 당산점", "마콘", "선유슬로우", "당산끝집", "참새방앗간", "계탄몽", "다래칼국수", "경아식당 당산점",
"논키", "이자카야 베이비", "고양진김치찌개 당산직영점", "피크닉앤", "코지로 당산역점", "선유골목집", "반카페", "코하루", "디데이원", "명동칼국수 선유점",
"야키토리 베이비", "싱싱해포차", "my own garden", "당산계단집", "청록미나리식당 당산점", "당산진미관", "브라이트사이즈", "옥된장 당산점", "카페설리번 당산점",
"더스티", "서울객점 당산양평점", "연참치", "카페 이파네마", "바지락칼국수&아구찜,보쌈", "후무", "퍼스트커피랩 당산역점", "말론하우스", "당산항",
"전주이모네식당", "안단단", "파니피카", "커피101스트릿 당산점", "스쿱앤그릭", "노버든", "브링미커피 브루어스", "우리쌀빵", "아키비스트 서울양평점", "플레블리 떡케이크",
"웨이프", "한숲", "밀로브레드", "헬로앨리스마켓24선유점", "예일타운 커피랩", "브런치빈 당산점", "치키차카초코 영등포점", "카페 오밀리우",
"호두붐 당산점", "진켈란젤로 치즈케이크", "흘러", "모닝캄커피랩 당산점", "초가오 영등포점", "오가다 영등포직영점", "쉬즈베이글 당산점", "만랩커피 당산중앙점",
"곳온니플레이스 OLD STREET", "코지로", "철이네", "23평", "일성옥", "바지락칼국수&아구찜,보쌈", "소백탄", "소공원", "월양", "내리다곰",
"쌀통닭 당산역점", "단토리 당산역점", "돈랩", "업스테어앤드", "당산 3.5 왕소금구이", "청춘냉동삼겹살", "호랭이반점 당산역점", "선유가츠",
"모어베지샐러드", "고흥수산"]
etc = ['오락시설', '한약국,한약방', '국토교통부', '영화관', '화장품,향수',
'문구,팬시용품', '네일아트,네일샵', '관리,안내', '침구,커튼',
'마사지, 지압', '체험여행', '특산물,관광민예품', '남성정장',
'고속도로휴게소', '웨딩컨설팅,플래너', '슈퍼,마트', '종합생활용품',
'기업', '공영주차장', '다이어트,비만', '주차장', '공방', '피부과',
'약국', '귀금속,시계', '가구', '폐업했거나 정보 제공이 중지된 장소',
'속눈썹증모,연장', '박물관', '성형외과', '스포츠용품', '화물운송',
'S', '안경원', '치과', '없음', '건강기능보조식품', '결혼예물', '애견용품',
'셀프,대여스튜디오', '동물병원', '드럭스토어', '왁싱,제모', '호텔', '종합패션',
'미용실', '공사,공단', '헬스장', '내과', '편의점', '미술관', '슈퍼,마트',
'GS칼텍스주유소', '전기,가스,수도사업', 'HD현대오일뱅크주유소', '약국',
'영화관', '종합가전', 'SK주유소', '고속도로휴게소', '종합생활용품',
'소프트웨어개발', '관람,체험', '유아,아동용품', '솔루션개발', '정장',
'남성의류', '신발', '유아동복', '상가,아케이드', '편의점', '화장실',
'S', '내과', '가방,핸드백', '등산,아웃도어', '카드단말기', '렌터카', '패션',
'절,사찰', '은행', '캐주얼웨어', '스포츠용품', '주차장', '판촉,기념품',
'문화센터', '장례식장', '문구,팬시용품', '호텔', '안경원', '여성의류',
'드럭스토어', '서점', '주유소', '민간자동차검사소', '산업용품', '치과',
'현금인출기', '갤러리,화랑', '도장', '미용실', '공영주차장', '전문건설업',
'국토교통부', '특산물,관광민예품', '타이어,휠', '국제,항공화물', '휴대폰수리',
'기업', '관리,안내', '정형외과', '도보코스', '콘도,리조트', '해수욕장,해변',
'온천,스파', '기부,모금단체', '자연,생태공원', '세탁', '우편취급소', '차',
'노래방', '세탁소', '전망대', '회관', '한의원', '패션잡화', '의류제작',
'조명,디스플레이', '명절 무료 개방 주차장', '신용조합', '산부인과',
'병원,의원', '콘택트렌즈전문', '정육점', '교습학원,교습소', '컨벤션센터',
'당구장']
options = Options()
options.add_argument("window-size=1920x1080")
service = Service(executable_path=ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=options)
user_URL_list = []
file_path = 'c:\\Users\\kimsy\\Desktop\\Filtered_Review_Sup.xlsx'
sheet_name = 'Sheet1' # 엑셀 파일의 경로
# 엑셀 파일을 읽습니다.
df = pd.read_excel(file_path, sheet_name = sheet_name)
start_name = "de****"
start_index = df[df.iloc[:, 1] == start_name].index[0]
# start_index 이후의 데이터를 가져옵니다.
User_data = df.iloc[start_index:, [0, 1, 7, 8]].values.tolist()
xlsx = Workbook()
file_name = f'Reviewer.xlsx'
list_sheet = xlsx.create_sheet('output')
list_sheet.append(['nickname', 'name','category', 'review', 'date', 'tags', 'numbers', 'OX'])
current_user_name = None
for u in User_data:
start_time = time.time()
user_origin = u[0].split('\n')[0]
user_nickname = u[1].split('\n')[0]
user_URL = u[2]
#user_visited = [item.strip() for item in u[3].split(', ')]
#user_visited.append(user_origin)
#print(user_visited)
current_user_name = user_nickname
driver.get(user_URL)
driver.implicitly_wait(5)
user_URL_list.append(user_URL)
photo_video_review_checkbox = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, 'onlyHasMedia')))
# 체크되어 있다면 클릭해서 해제
if photo_video_review_checkbox.is_selected():
driver.execute_script("arguments[0].click();", photo_video_review_checkbox)
time.sleep(2) # 잠시 대기하여 상태가 반영되도록 함
first_post = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button._5RYLm7.bEchjN')))
driver.execute_script("arguments[0].click();", first_post)
time.sleep(5)
for i in range(0,40):
for c in range(0,30):
driver.find_element(By.TAG_NAME, 'body').send_keys(Keys.PAGE_DOWN)
time.sleep(1)
try:
nickname = driver.find_element(By.CSS_SELECTOR, 'h1._3q8NFd').text.strip()
if nickname != user_nickname:
print("Something goes wrong!!! You should do it more better..!")
stores = driver.find_elements(By.CSS_SELECTOR, 'div._898uc8')
y = 0
for s in stores:
i_store_review = s.find_elements(By.CSS_SELECTOR, 'div.pui__vn15t2')
if i_store_review and not i_store_review[0].text.strip():
store_review = "없음"
else:
store_review = s.find_element(By.CSS_SELECTOR, 'div.pui__vn15t2').text.strip()
if store_review != "없음":
store_name = s.find_element(By.CSS_SELECTOR, 'span.pui__pv1E2a').text.strip()
i_store_category = s.find_elements(By.CSS_SELECTOR, 'div.pui__Vb-OW1')
if i_store_category and not i_store_category[0].text.strip():
store_category = "없음"
elif any("폐업" in element.text for element in i_store_category):
store_category = "폐업했거나 정보 제공이 중지된 장소"
else:
store_category = s.find_element(By.CSS_SELECTOR, 'span.pui__WUm6H8').text.strip()
if store_category not in etc:
# 방문일\n7.28.일\n년 7월 28일 일요일 으로 뜨는 것을 수정해야함
i_store_date = s.find_element(By.CSS_SELECTOR, 'span.pui__gfuUIT').text.strip()
line = i_store_date.split('\n')
store_date = line[-2]
# revisit "번째 방문" 문자 제거
revisit_elements = s.find_elements(By.CSS_SELECTOR, 'span.pui__gfuUIT')
revisit = revisit_elements[1].text.strip() if len(revisit_elements) > 1 else ''
if revisit:
revisit = int(revisit[:-5])
# 태그 더보기 클릭 후 리뷰 태그 수집
i_tags = [tag.text.strip() for tag in s.find_elements(By.CSS_SELECTOR, 'div.pui__HLNvmI')]
i_tags = str(i_tags)
if "+" not in i_tags:
i_tag = [tag.text.strip() for tag in s.find_elements(By.CSS_SELECTOR, 'div.pui__HLNvmI span.pui__jhpEyP')]
else:
tag_button = s.find_element(By.CSS_SELECTOR, 'a.pui__jhpEyP.pui__ggzZJ8')
driver.execute_script("arguments[0].click();", tag_button)
time.sleep(1)
i_tag = [tag.text.strip() for tag in s.find_elements(By.CSS_SELECTOR, 'div.pui__HLNvmI span.pui__jhpEyP')]
# 초기 타깃 가게에 해당하는지 여부 체크
for v in P_names:
if str(store_name) != str(v):
OX = "X"
else:
OX = "O"
break
# 엑셀에 저장
list_sheet.append([nickname, store_name, store_category, store_review, store_date, ", ".join(i_tag), revisit , OX])
y = y+1
xlsx.save(file_name)
end_time = time.time()
elapsed_time = int(end_time - start_time)
print(f"Data collection completed and saved to Excel. number = {y}, (time = {elapsed_time})")
if elapsed_time < 200 and y < 150:
print(f"이름: {user_nickname}, 시간:{elapsed_time}, 횟수:{y}, 마지막 날짜:{store_date}")
except Exception as e:
print('Error:', e)
print(f"Data collection completed up to place: {current_user_name}. Data saved to Excel.")
# Excel 파일 저장 및 드라이버 종료
xlsx.save(file_name)
driver.quit()
print("Data collection completed and saved to Excel.")
오늘은 네이버 플레이스에서 유저별 리뷰를 크롤링하는 코드를 정리해 보았습니다.
웹 크롤링을 제대로 해보는 건 처음이나 꽤나 많은 인풋을 들인 것 같은데요... ㅎㅎ
그래도 한 번 해봤으니 다음부터는 조금 더 효율적으로 코드를 짤 수 있을 것 같습니다.
* 질문이나 피드백 환영입니다!
'code' 카테고리의 다른 글
Python | 웹 크롤링 | 네이버 플레이스 리뷰 크롤링 (1) (5) | 2024.08.19 |
---|