티스토리 뷰
원래 목적은 AI agent에게 사람이 하는 것과 같은 방법으로 자료를 조사하고, 원하는 카페를 찾게하기 위해 selenium을 이용해 동적 크롤링을 해보았다.
그런데 정적 크롤링과 달리 하나씩 직접 클릭하며 자료를 얻다 보니 생각보다 시간이 오래 걸려 방법을 바꿔야하지 않나 고민중이다.
전에 selenuim을 이용해 크롤링을 했을때는 chromdriver를 크롬 버전에 맞게 따로 설치를 했었는데, 이제는 cmd에 간단히 명령어 입력으로 사용할 수 있었다.
pip install webdriver-manager
네이버 지도 api로는 리뷰를 가져올 수 없어 직접 크롤링을 해보았다. 네이버 지도의 경우 iframe을 통해 하나의 웹브라우저 안에 여러개의 html 파일이 중첩되어있는 구조였다. 카페의 이름을 클릭하면 가게의 상세페이지가 들어있는 새로운 iframe이 추가되는데, iframe안에 iframe이 생기는게 아닌, 병렬적으로 추가되었다. 그래서 iframe을 초기화하고 다시 전환을 해줘야 했다.
* iframe이란?
- HTML 문서 내에서 다른 HTML 문서를 삽입할 수 있는 요소
- 웹 페이지 안에 또 다른 웹 페이지를 포함할 수 있게 해주는 HTML 태그
또 다음 명령어를 실행하기 전에는 time.sleep()을 이용해 데이터가 들어올 때까지 기다려야 했는데, WebDriverWait을 이용해 구현할 수 있엇다.
def naver_place_tool():
"""
네이버 지도에서 사용자 요청에 맞는 카페를 찾고, 카페의 특징과 분위기, 시그니처 메뉴를 분석하기 위해 사진과 최신 리뷰를 수집
"""
cafe_info = {}
# 크롬 드라이버 설정
options = webdriver.ChromeOptions()
options.add_experimental_option("detach", True) # 창이 자동으로 닫히지 않게 설정
driver = webdriver.Chrome(options=options)
# 네이버 지도 접속
url = "https://map.naver.com/v5/search"
driver.get(url)
# 검색창 요소 찾기 (WebDriverWait 사용)
search_box = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "input_search"))
)
# 검색어 입력
search_box.send_keys("강릉 오션뷰 카페")
# 검색 실행 (ENTER 키)
search_box.send_keys(Keys.ENTER)
# `searchIframe`으로 전환
try:
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.ID, "searchIframe"))
)
except:
print("searchIframe을 찾을 수 없음")
driver.quit()
exit()
# 검색 결과 요소 가져오기 (결과가 여러 개일 수도 있으므로 `find_elements` 사용)
try:
cafe_list = WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.CLASS_NAME, "TYaxT"))
)
print(f"{len(cafe_list)}개의 카페를 찾았습니다.")
except:
print("cafe_list를 찾을 수 없음")
driver.quit()
exit()
if cafe_list:
for i in range(7):
cafe_name = cafe_list[i].text.strip()
cafe_info[cafe_name] = {"reviews": [], "images": []}
cafe_list[i].click()
driver.switch_to.default_content()
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.ID, "entryIframe"))
)
try:
# 리뷰 버튼 찾고 클릭
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//span[text()='리뷰']"))
).click()
# 리뷰 나타날때까지 기다렸다가 스크롤
time.sleep(2)
driver.execute_script("window.scrollBy(0, window.innerHeight);")
# 최신순 버튼 찾고 클릭
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//a[text()='최신순']"))
).click()
# 최신 리뷰 기다렸다가 크롤링
time.sleep(2)
review_list = WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.XPATH, "//div[@class='pui__vn15t2']/a"))
)
# 최신 리뷰 10개
for idx, review in enumerate(review_list):
review_text = review.text # 리뷰 텍스트 가져오기
if review_text != "더보기":
cafe_info[cafe_name]["reviews"].append(review_text)
image_list = WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.XPATH, "//a[@class='place_thumb']/img"))
)
# 이미지 10개
for idx, img in enumerate(image_list):
img_url = img.get_attribute("src") # 이미지 URL 가져오기
cafe_info[cafe_name]["images"].append(img_url)
driver.switch_to.default_content()
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.ID, "searchIframe"))
)
except:
print("리뷰 버튼이 없습니다.")
result = json.dumps(cafe_info, ensure_ascii=False, indent=4)
print(result)
return result
반응형
'AI > AI 서비스 개발' 카테고리의 다른 글
[AI 서비스 개발] CI/CD - Github action 이용해 AWS 자동 배포하기 (0) | 2025.01.30 |
---|---|
[AI 서비스 개발] Nginx, AWS EC2, docker-compose로 배포하기 (0) | 2025.01.30 |
[AI 서비스 개발] dict와 json (1) | 2025.01.29 |
[AI 서비스 개발] 웹검색 api 비교 (1) | 2025.01.28 |
[AI 서비스 개발] 백엔드와 DB연결, Session (1) | 2025.01.27 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 오블완
- 고득점 Kit
- 영어회화
- 운동
- 미라클모닝
- 실기
- IH
- 30분
- 아침운동
- llm
- 루틴
- 기초
- C언어
- 경제
- 뉴스
- 스크랩
- 다이어트
- 오픽
- ChatGPT
- Ai
- 빅데이터 분석기사
- SQL
- 줄넘기
- 습관
- opic
- 티스토리챌린지
- Python
- 아침
- 갓생
- 프로그래머스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함