tak's data blog

[BOAZ 프로젝트] 카카오맵 카페 크롤링1 본문

BOAZ

[BOAZ 프로젝트] 카카오맵 카페 크롤링1

hyuntaek 2021. 3. 9. 17:48
반응형
SMALL

 

 

 

계속 프로젝트를 진행 중에 있습니다. 현재는 네이버 / 카카오 / 구글 별로 크롤링 코드를 각자 짜오는 과정을 가지고 있는데 카카오 맵의 리뷰 페이지가 넘어가는 규칙이 특이해 쉽지 않네요...

 

 

BeautifulSoup과 Selenium을 통한 크롤링을 위해서 xpath경로가 필요합니다. 

하지만 카카오맵은 페이지가 넘어 갈 때의 경로가 

1. 페이지가 2개이하면 em -> a
2. 페이지가 4개이하면 em -> a[1] -> a[2] -> a[3]
3. 페이지가 5개면 a[1] -> a[2] -> a[3] -> a[4] -> em
4. 페이지가 2개이상이면 다음버튼 까지 em -> a[1] -> a[2] -> a[3] -> a[4] -> a[5](다음) 
5. 다음으로 넘어가면 이전이 a[1] -> em(6페이지) ->  a[2] -> a[3] -> a[4] -> a[5] -> a[6](다음페이지)

이런식으로 페이지의 갯수별로 상이합니다.

 

 

그래서

페이지를 2-5페이지 / 6페이지 이상으로 나누어 크롤링 코드를 어느정도 구현해보았습니다.

 

 

크롤링 코드(거의 완료) page수까지 세주는 함수

1) 수정 전

comment_list / rating_list / userid_list / user_url_list 와 같이 리뷰 / 별점 / user고유 아이디 / user_url 리스트를 만들어 준 다음에 크롤링을 통해 합쳐서 나중에 학습을 위해 데이터프레임으로 뽑아낼 예정입니다.

 

카카오맵은 5페이지 이하의 리뷰를 수집하려면 각각의 페이지별로 넘기는 경로의 규칙이 달라

위와 같이 페이지별로 짜느라 애를 먹었습니다 ... 어찌저찌 했는데 돌아가기는 잘돌아가는것 같지만 효율이 너무 떨어지는게 아닌가 생각합니다. 

 

2) 수정 전

현재 문제점은 오래된 리뷰들은 user정보가 없어 user_id와 같이 정보를 뽑아낼 수 없는 상황입니다. 그래서 데이터프레임을 형성하는 상황에서 행의 수가 맞지않아 null값이 존재할 것입니다. 이 과정을 한번에 처리하는 코드와 좀 더 효율성이 좋게 다시 다듬어야 할 과정이 필요한 상황입니다. 

 

 

 

 

3) 수정 후

driver = webdriver.Chrome(r'C:/Users/user/Desktop/dd/Data_Handling/chromedriver.exe')
driver.maximize_window() 


count = 0
current = 0
goal = len(items)
for item in items :
    current += 1
    print('진행상황 : ', current,'/',goal,sep="")
    # 리뷰가 없을 때의 코드
    driver.get("https://map.kakao.com/") # 카카오 지도 접속하기
    searchbox = driver.find_element_by_xpath("//input[@id='search.keyword.query']") # 검색창에 입력하기
    searchbox.send_keys(item)
    time.sleep(2)
    searchbutton = driver.find_element_by_xpath("//button[@id='search.keyword.submit']") # 검색버튼 누르기
    driver.execute_script("arguments[0].click();", searchbutton)
    time.sleep(2)
    
    if len(driver.find_elements_by_xpath("//a[@class='moreview']")) != 0:
        print('식당 존재')
        driver.execute_script('window.open("about:blank", "_blank");') # 새 탭 열기
        reviewbutton = driver.find_element_by_xpath("//a[@class='numberofscore']")
        time.sleep(2)
        content_url = reviewbutton.get_attribute("href") 
        tabs = driver.window_handles
        driver.switch_to_window(tabs[1]) # 새 탭으로 이동
        driver.get(content_url) # 링크 열기
        time.sleep(3)
        html = driver.page_source
        soup = BeautifulSoup(html, 'html.parser')
        review_lists = soup.select('.list_evaluation > li')
        print(len(review_lists))
        if len(review_lists) != 0 :
            for i, review in enumerate(review_lists) :
                user_review = review.select('.txt_comment > span') # 리뷰
                rating = review.select('.grade_star > em') # 별점
                try:
                    img_url = review_lists[i].select_one('a.link_photo > img ')['src']
                except:
                    continue
                user_id = review.select('.append_item > a[data-userid]') # user 정보 html 파싱
                timestamp = review.select(' div > span.time_write') #시간정보
                try:
                    row = {"UserID":user_id[0].get('data-userid'),"ItemID":item,"Rating":rating[0].text,"Timestamp":timestamp[0].text}
                    row = pd.DataFrame(row, index=[i])
                    rating_df = rating_df.append(row,ignore_index=True)
                    review_row = {"ItemID" : item, "review" : user_review[0].text}
                    review_row = pd.DataFrame(review_row, index=[i])
                    review_elem = review_elem.append(review_row, ignore_index = True)
                    try :
                        img_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "img_url" : img_url}
                        img_row = pd.DataFrame(img_row, index=[i])
                        img_elem = img_elem.append(img_row, ignore_index=True)
                    except :
                        img_row = {"UserID":None,"ItemID" : item, "img_url" : None}
                        img_row = pd.DataFrame(img_row, index=[i])
                        img_elem = img_elem.append(img_row, ignore_index=True)

                    time.sleep(3)
                except:
                    row = {"UserID":None,"ItemID":item,"Rating":None,"Timestamp":timestamp[0].text}
                    row = pd.DataFrame(row, index=[i])
                    rating_df = rating_df.append(row,ignore_index=True)
                    review_row = {"ItemID" : item, "review" : user_review[0].text}
                    review_row = pd.DataFrame(review_row, index=[i])
                    review_elem = review_elem.append(review_row, ignore_index = True)
                    try :
                        img_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "img_url" : img_url}
                        img_row = pd.DataFrame(img_row, index=[i])
                        img_elem = img_elem.append(img_row, ignore_index=True)
                    except :
                        img_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "img_url" : None}
                        img_row = pd.DataFrame(img_row, index=[i])
                        img_elem = img_elem.append(img_row, ignore_index=True)
                    time.sleep(1)

                
                    
        else :
            print("리뷰가 없습니다")
            
        try:
            for i in range(2,500):
                time.sleep(3)
                another_review = driver.find_element_by_xpath("//a[@data-page='" + str(i) + "']")
                another_review.click()
                time.sleep(3)
                html = driver.page_source
                soup = BeautifulSoup(html, 'html.parser')
                review_lists = soup.select('.list_evaluation > li')
                if len(review_lists) != 0 :
                    for i, review in enumerate(review_lists) :
                        user_review = review.select('.txt_comment > span') # 리뷰
                        rating = review.select('.grade_star > em') # 별점
                        try:
                            img_url = review_lists[i].select_one('a.link_photo > img ')['src']
                        except:
                            continue
                        user_id = review.select('.append_item > a[data-userid]') # user 정보 html 파싱
                        timestamp = review.select(' div > span.time_write') #시간정보
                        try:
                            row = {"UserID":user_id[0].get('data-userid'),"ItemID":item,"Rating":rating[0].text,"Timestamp":timestamp[0].text}
                            row = pd.DataFrame(row, index=[i])
                            rating_df = rating_df.append(row,ignore_index=True)
                            review_row = {"UserID":user_id[0].get('data-userid'), "ItemID" : item, "review" : user_review[0].text}
                            review_row = pd.DataFrame(review_row, index=[i])
                            review_elem = review_elem.append(review_row, ignore_index = True)
                            try:
                                img_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "img_url" : img_url}
                                img_row = pd.DataFrame(img_row, index=[i])
                                img_elem = img_elem.append(img_row, ignore_index=True)
                            except:
                                img_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "img_url" : None}
                                img_row = pd.DataFrame(img_row, index=[i])
                                img_elem = img_elem.append(img_row, ignore_index=True)
                            time.sleep(1)
                            
                        except:
                            row = {"UserID":None,"ItemID":item,"Rating":None,"Timestamp":timestamp[0].text}
                            row = pd.DataFrame(row, index=[i])
                            rating_df = rating_df.append(row,ignore_index=True)
                            review_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "review" : user_review[0].text}
                            review_row = pd.DataFrame(review_row, index=[i])
                            review_elem = review_elem.append(review_row, ignore_index = True)
                            try :
                                img_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "img_url" : img_url}
                                img_row = pd.DataFrame(img_row, index=[i])
                                img_elem = img_elem.append(img_row, ignore_index=True)
                            except :
                                img_row = {"UserID":user_id[0].get('data-userid'),"ItemID" : item, "img_url" : None}
                                img_row = pd.DataFrame(img_row, index=[i])
                                img_elem = img_elem.append(img_row, ignore_index=True)
                            
                        
                            
        except:
            print("더 이상 리뷰 존재 X")
            driver.close()
        driver.switch_to_window(tabs[0])
        print("기본 페이지로 돌아가자")
            
    else:
        print("식당 존재 x")

 

 

 

 

그래도 크롤링 코드를 이렇게 짜보는게 처음이라 많이 배웠다고 생각합니다. 이것저것 부딪혀보면서 결과물을 내보니 뿌듯하기는 한 것 같습니다! 

 

 

반응형
LIST