본문 바로가기
BIG DATA STUDY/Python

네이버 플레이스 리뷰 데이터 크롤링

by StrongRiver 2022. 5. 4.
728x90
반응형

네이버 플레이스의 리뷰 데이터를 크롤링 하기 위해

 

셀레니움을 사용해서 데이터를 모아보았으나,

 

리뷰가 만오천개 이상일 경우 메모리 부족으로 크롤링이 중단 되는 문제가 있었다

 

그래서 graphQL 활용 방식으로 데이터를 수집하였다.

 


캐리비안베이 리뷰 데이터 수집 방법

네이버 리뷰를 리퀘스트 받아 데이터 프레임으로 저장하기 위해 다음과 같이 Import해준다.


import requests
import math
from time import sleep
import numpy as np
import pandas as pd

네이버 지도에서 캐리비안베이를 검색하면 아래와 같은 화면이 나온다.

이 상태에서 F12를 눌러 개발자 툴을 열어준다.

 

개발자 툴에서 아래 사진과 같이 캐리비안베이 리뷰 정보가 Preview화면에 나타나도록 파일을 찾아준다.

Network - All - Name

(Type =document인 파일 중에 있다)

 

우측의 Headers를 클릭하여 Request URL과 스크롤 해서 맨 밑에 user-agent를 복사해준다.

복사한 정보를 아래와 같이 입력한다.


headers = {
    'referer': 'https://pcmap.place.naver.com/place/12113040?entry=pll&from=map&fromPanelNum=2&ts=1651661053225',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36'
}

헤더 정보를 입력했으니 graphQL 정보를 받아야한다.

리뷰 데이터의 정보를 확인하기 위해 방분자 리뷰를 클릭해 리뷰를 확인한다.

 

 

리뷰 화면을 띄운 상태의 개발자 툴에서 아래와 같이 Fetch/XHR에 들어가 graphql의 Payload를 확인한다.

데이터 내용이 getVisitorReviews인 graphql을 찾으면 된다.

 

Payload의 요약을 다 펼쳐주면 다음과 같은 정보가 나오는데 표기한 정보들을 가져와 코드에 입력해주면 된다.


data = dict(
    operationName= "getVisitorReviews",
    query="query getVisitorReviews($input: VisitorReviewsInput) { visitorReviews(input: $input) { items { id rating author { id nickname from imageUrl objectId url review { totalCount imageCount avgRating __typename } theme { totalCount __typename } __typename } body thumbnail media { type thumbnail class __typename } tags status visitCount viewCount visited created reply { editUrl body editedBy created replyTitle __typename } originType item { name code options __typename } language highlightOffsets apolloCacheId translatedText businessName showBookingItemName showBookingItemOptions bookingItemName bookingItemOptions votedKeywords { code iconUrl iconCode displayName __typename } userIdno isFollowing followerCount followRequested loginIdno __typename } starDistribution { score count __typename } hideProductSelectBox total showRecommendationSort __typename } }",
    variables=dict(
        id="1648854291",#입력
        input={
            "bookingBusinessId": "null",#입력
            "businessId": "1648854291",#입력
            "businessType": "place",
            "cidList": ["222117","222121","222160","232110"],#입력
            "display": 20, #한번에 몇개의 정보를 불러올지 설정
            "getAuthorInfo": True,
            "includeContent": True,
            "includeReceiptPhotos": True,
            "isPhotoUsed": False,
            "item": "0",
            "page": now_loop_count+1
            }

 

이렇게 하면 필요한 정보는 모두 얻었은 상태다.

 

하기 코드의 display값을 수정하면 한번에 불러오는 데이터 양을 조절가능한데, 한번에 너무 많은 값을 불러오면

 

429에러가 발생할 수 있다.

 


review_data = pd.DataFrame(data=[], columns=['별점','리뷰'])
total_item_no = None

now_loop_count = 0
total_loop_count = 10000
total_item = 0

while True:
    if total_loop_count<=now_loop_count:
        break
    data = dict(
    operationName= "getVisitorReviews",
    query="query getVisitorReviews($input: VisitorReviewsInput) { visitorReviews(input: $input) { items { id rating author { id nickname from imageUrl objectId url review { totalCount imageCount avgRating __typename } theme { totalCount __typename } __typename } body thumbnail media { type thumbnail class __typename } tags status visitCount viewCount visited created reply { editUrl body editedBy created replyTitle __typename } originType item { name code options __typename } language highlightOffsets apolloCacheId translatedText businessName showBookingItemName showBookingItemOptions bookingItemName bookingItemOptions votedKeywords { code iconUrl iconCode displayName __typename } userIdno isFollowing followerCount followRequested loginIdno __typename } starDistribution { score count __typename } hideProductSelectBox total showRecommendationSort __typename } }",
    variables=dict(
        id="1648854291",#입력
        input={
            "bookingBusinessId": "null",#입력
            "businessId": "1648854291",#입력
            "businessType": "place",
            "cidList": ["222117","222121","222160","232110"],#입력
            "display": 20, #한번에 몇개의 정보를 불러올지 설정
            "getAuthorInfo": True,
            "includeContent": True,
            "includeReceiptPhotos": True,
            "isPhotoUsed": False,
            "item": "0",
            "page": now_loop_count+1
            }
        )
    )
    resp = requests.post('https://pcmap-api.place.naver.com/place/graphql',
                     headers=headers,
                     json=data)
    data = resp.json()
    
    total_item = data['data']['visitorReviews']['total']
    if total_item_no is None and total_item:
        # 첫 시작 & 요청 제대로
        total_item_no = total_item
        total_loop_count = math.ceil(total_item_no/10)
        now_loop_count+=1
        
        print("첫시작 응답 잘 옴")
        print("total개수;", total_item_no)
        
    elif total_item_no is None and not total_item:
        # 요청 제대로 안 옴 & 첫 시작 
        print(" 요청 제대로 안 옴 & 첫 시작  => 기다림")
        sleep(3)
        continue
        
        
    elif not total_item and not total_item_no:
        # 첫 시작 X & 응답 안줌 => 기다림
        sleep(3)
        print("첫 시작 X & 응답 안줌 => 기다림")
        continue
        
    elif total_item_no and total_item:
        # 첫 시작 X  & 응답도 잘 옴
        now_loop_count+=1
        sleep(1)
        print("응답 잘 옴 ")
    else:
        print("첫 시작 X & 응답 안줌")
        print("total item: ", total_item, "\n total_item_no:", total_item_no)
        sleep(3)
        continue
    
    
        
    items = data['data']['visitorReviews']['items']
    print("{}페이지 items개수 {}".format(now_loop_count, len(items)))
    
    #데이터 프레임 저장
    for item in items:
        tmp = []
        tmp.append(str(item['rating']) + " " + str(item['created']))
        tmp.append(item['body'])
        tmp = pd.DataFrame(data=[tmp], columns=review_data.columns)
        review_data = pd.concat([review_data,tmp])

 

728x90
반응형

'BIG DATA STUDY > Python' 카테고리의 다른 글

파이썬 배우기 #Pandas  (0) 2022.01.25
파이썬 배우기 #11 행렬2  (0) 2022.01.21
파이썬 배우기 #10 numpy, 행렬  (0) 2022.01.20
파이썬_연습문제  (0) 2022.01.19
파이썬 배우기 #9 파이썬 내장함수  (0) 2022.01.18

댓글