해결된 질문
작성
·
1.7K
1
'''
네이버지도에 표시되는 순서대로
순위, 가게명, 별점, 방문자리뷰수, 블로그리뷰수를 엑셀에 저장(1페이지만)
주의사항
광고는 제외, 별점이 있는 가게만 크롤링한다.
방문자 리뷰가 없다면 0으로 수집, 블로그 리뷰가 없다면 0으로 수집한다.
iframe을 만났을때 대처방법.
무한 스크롤 처리 방법 고민.
'''
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import pyautogui
import time
from bs4 import BeautifulSoup
import openpyxl
#크롬 드라이버 자동 업데이트
from webdriver_manager.chrome import ChromeDriverManager
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
}
keyword = pyautogui.prompt("검색어를 입력하세요>>>")
wb = openpyxl.Workbook()
ws = wb.create_sheet(keyword)
ws.append(["순위","가게명","별점","방문자 리뷰수","블로그 리뷰수"])
chrome_options = Options()
#브라우저 꺼짐 방지
chrome_options.add_experimental_option("detach", True)
#불필요한 에러 메시지 없애기
chrome_options.add_experimental_option("excludeSwitches", ["enable-logging"]) # 셀레니움 로그 무시
serivce = Service(executable_path=ChromeDriverManager().install())
browser = webdriver.Chrome(service=serivce, options=chrome_options)
#웹페이지 해당 주소 이동
browser.implicitly_wait(5)
browser.maximize_window()
browser.get("https://map.naver.com/p?c=15.00,0,0,0,dh")
search = browser.find_element(By.CSS_SELECTOR,".input_search")
search.click()
time.sleep(1)
search.send_keys(f"{keyword}")
time.sleep(1)
search.send_keys(Keys.ENTER)
time.sleep(1)
#iframe 안으로 들어가기
browser.switch_to.frame("searchIframe")
#iframe 밖으로 나오기
#browser.switch_to.default_content()
browser.find_element(By.CSS_SELECTOR,"#_pcmap_list_scroll_container").click()
lists = browser.find_elements(By.CSS_SELECTOR,"li.UEzoS")
before_scroll = len(lists)
while True :
before_scroll = len(lists)
for i in range(0,10) :
browser.find_element(By.CSS_SELECTOR,"body").send_keys(Keys.PAGE_DOWN)
time.sleep(0.5)
lists = browser.find_elements(By.CSS_SELECTOR,"li.UEzoS")
after_scroll = len(lists)
if before_scroll == after_scroll :
break
# lists = browser.find_elements(By.CSS_SELECTOR,"li.UEzoS.rTjJo")
print(f"총 {after_scroll}개의 가게가 있습니다.")
num = 0
for list in lists :
if len(list.find_elements(By.CSS_SELECTOR,"li>a.gU6bV")) == 0 :
store = list.find_element(By.CSS_SELECTOR,"span.TYaxT")
browser.execute_script("arguments[0].click();", store)
time.sleep(1)
browser.switch_to.default_content()
browser.switch_to.frame("entryIframe")
# html_entry = browser.page_source
# soup_entry = BeautifulSoup(html_entry, 'html.parser')
if len(browser.find_elements(By.CSS_SELECTOR,"#app-root > div > div > div > div.place_section.OP4V8 > div.zD5Nm.f7aZ0 > div.dAsGb > span.PXMot.LXIwF")) > 0 :
num += 1
title = browser.find_element(By.CSS_SELECTOR,".Fc1rA").text
stars = float(browser.find_element(By.CSS_SELECTOR,".LXIwF > em").text)
visitor_review = browser.find_element(By.CSS_SELECTOR,"div.dAsGb > span:nth-child(2)").text
blog_review = browser.find_element(By.CSS_SELECTOR,"div.dAsGb > span:nth-child(3)").text
visitor_review = int(visitor_review.replace("방문자리뷰 ","").replace(",",""))
blog_review = int(blog_review.replace("블로그리뷰 ","").replace(",",""))
print(num,title,stars,visitor_review,blog_review)
ws.append([num,title,stars,visitor_review,blog_review])
browser.switch_to.default_content()
browser.switch_to.frame("searchIframe")
wb.save(f"/Chapter05/{keyword}.xlsx")
안녕하세요 강사님.
현재 네이버 지도에서 강남역 맛집을 검색하면 강의 노트와 같이 방문자 리뷰, 블로그 리뷰를 크롤링하기 위해서는 해당 가게를 클릭하고 그 iframe으로 들어가서 데이터를 받아와야합니다.
그래서 위와 같이 코드를 작성하였는데요.
문제는 가게이름 클릭 후 페이지 로딩을 고려한 지연시간을 1초 밖에 안줬는데. 가게이름, 별점, 리뷰수를 읽어오는데 굉장히 오래걸립니다.(5~6초 이상 소요). 이 때문에 전체 리스트에 대한 정보를 받아오는 시간이 너무 많이 소요되는데요.
혹시 이를 개선할수있는 방안이 있을까요?
답변 3
0
0
안녕하세요~
수강생님 제가 최근에 일이 바쁘고 몸이 안좋아서 답변이 조금 늦었는데
이해 좀 부탁드리겠습니다 ㅜㅜ
가게당 5~6초정도 추가로 시간이 걸리는 것은,
광고태그가 없는 가게를 바로 넘어가지 않고 5초동안 기다려서 생기는 현상이었습니다.
list.find_elements(By.CSS_SELECTOR,"li>a.gU6bV") # 여기서 문제 발생
해결방법은 아래와 같습니다.
browser.implicitly_wait(5)
옵션을 주지 않으면 태그를 찾지 못해도 바로 넘어갑니다.
그럼 즐거운 크롤링 되세요 ^^
0
스트기능을 사용해 파이썬으로 웹 크롤링을 하고 계신 것 같습니다. 속도 개선을 위해 몇 가지 방법을 제안해 드릴게요.
headless 모드 사용하기: 화면을 렌더링하지 않고 크롤링을 진행하는 방법입니다. ChromeOptions 객체의 add_argument("--headless")
를 추가하여 사용하실 수 있습니다.
WebDriverWait 사용하기: 대기시간을 정확하게 지정하여 요소가 나타날 때까지 기다릴 수 있습니다. WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.XPATH, "xpath")))
와 같은 식으로 사용할 수 있습니다.
BeautifulSoup 대신 Selenium으로 파싱하기: BeautifulSoup 대신 Selenium의 driver.find_element()
와 같은 메소드를 사용하여 파싱을 진행할 수 있습니다.
병렬 처리: 멀티 스레딩 또는 비동기 처리를 통해 여러 작업을 동시에 처리하는 방법으로 속도를 개선할 수 있습니다. concurrent.futures
라이브러리를 사용하여 병렬 처리를 구현할 수 있습니다.
무한 스크롤 처리: 스크롤을 내리면서 무한 스크롤을 처리해야 할 경우, 스크롤을 내린 후 일정 시간 동안 대기한 다음, 스크롤을 더 내리는 작업을 반복하는 방법을 사용할 수 있습니다. time.sleep()
과 pyautogui.scroll()
함수를 이용하는 방법이 있습니다.
이러한 방법들을 활용하여 속도를 개선해보세요. 그리고 작성하신 코드에 크롤링을 위한 코드가 없어서 정확한 도움을 드리기 어렵습니다. 크롤링에 사용하는 코드를 공유해주시면 더 자세한 도움을 드릴 수 있을 것 같아요.
답변 감사드립니다.!
그런데 말씀하신 implicitly_wait를 어디에 넣어줘야하나요??