brunch

You can make anything
by writing

C.S.Lewis

by 라인기 Sep 09. 2024

바이낸스(암호화폐 거래소) 사용자 리뷰 분석해 보기

크롤링과 NMF 분석을 활용해서 

 이번 글에서는 파이썬을 이용해 최대 암호화폐 거래소인 바이낸스의 리뷰 데이터를 수집하고(크롤링) NMF 방식을 이용해 사용자 리뷰를 분석해보려고 한다.


 '바이낸스'의 사용자 리뷰는 Trustpilot에서 수집했다.

Trustpilot은 714,000개 이상의 웹사이트에 대한 1억 6,700만 개 이상의 리뷰를 보유한 리뷰 플랫폼이다.

https://www.trustpilot.com/review/binance.com



리뷰 예시

우선, Trustpilot에서 페인 포인트 분석을 위해 5점 만점의 리뷰 중 3점 이하의 리뷰들만 수집했다.

먼저 해당 리뷰 분석을 위해 필요한 것들을 살펴보자.


준비물 및 설치

1. 파이썬 설치 및 필요 라이브러리 설치

https://myjamong.tistory.com/45

 > selenium/ pandas /googletrans 모듈을 설치하기 위해 알아둬야 한다. 

 > 터미널에서 직접 pip [모듈명]으로 설치할 수도 있다.


2. 엑셀

 > 크롤링한 데이터를 정리하기 위해 엑셀 파일이 필요하다. 


3. Chat GPT 4o(고급 데이터 분석을 위해 필요) 

 > 무료 버전 GPT에서는 1~2번 요청하면 더 이상 고급 데이터 분석이 불가능하다. 하루에 요청할 수 있는 양이 한정적이기 때문이다.


크롤링은 파이썬을 이용해 리뷰를 수집해 오기 위해 사용했고 NMF는 수집한 데이터에서 특정 키워드 빈도를 확인하기 위해 사용했다.


크롤링(Crawling)
인터넷상의 웹 페이지에서 데이터를 자동으로 수집하는 과정을 의미. 이를 통해 특정 사이트의 텍스트, 이미지, 링크 등의 정보를 수집 가능
NMF(Non-negative Matrix Factorization)
텍스트 데이터를 분석해 주요 주제나 패턴을 식별하는 데 유용한 분석 방법.
리뷰 데이터를 분석해 사용자들이 어떤 주제에 대해 주로 언급하는지 파악할 수 있음


NMF 분석은 Chat GPT의 도움을 받았다. Chat GPT 4o를 이용하면 고급 데이터 분석 기능을 이용할 수 있기 때문이다. 물론 크롤링을 하기 위한 파이썬 코드 역시 Chat GPT의 도움을 받았다.


리뷰에서 수집한 데이터

아이디 - 사용자의 이름.

국가 - 사용자가 리뷰를 작성한 국가.

작성일자 - 리뷰가 작성된 날짜.

내용 1 - 리뷰 내용.(영문)

내용 2- 리뷰 내용.(국문, 구글 번역 이용)

별점 - 사용자가 부여한 별점.

추천 수 - 리뷰가 유용하다고 표시된 횟수.


웹사이트에서 해당 데이터를 추출하여 엑셀 파일로 저장했다.

또한 추가 페이지가 있는 경우에는 페이지를 이동 모든 데이터를 수집할 수 있도록 했다. 


진행하는 시각화에 국가와 별점 등은 중요하지 않았지만 추후 필요하다 생각해 함께 추출했다.

추천 순이 높은 리뷰는 다수의 사용자가 함께 공감하는 데이터로 중요도를 높게 볼 수 있다고 생각했고 국가는 서비스 타깃 지역의 페인포인트를 확보하는데 도움이 될 것이라고 판단했다.


이제 파이썬 코드를 보자.



파이썬 코드

1. Trustpilot 페이지 열기

2. 해당 페이지의 바이낸스 리뷰 데이터 수집

3. 데이터 수집 시 다음 페이지로 이동

4. 데이터 수집 반복

5. 더 이상 리뷰 페이지가 존재하지 않을 경우 수집 종료

6. 영문 리뷰 데이터를 국문으로 번역 

7. 엑셀에 데이터 저장


from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time
import pandas as pd
from datetime import datetime
from googletrans import Translator  # 번역 라이브러리

# 국가 코드와 국가명 매핑
country_mapping = {
    "US": "United States", "KR": "South Korea", "GB": "United Kingdom", "DE": "Germany",
    "FR": "France", "JP": "Japan", "CN": "China", "IN": "India", "BR": "Brazil", "CA": "Canada",
    "AU": "Australia", "IT": "Italy", "ES": "Spain", "RU": "Russia", "MX": "Mexico", "ZA": "South Africa",
    "AR": "Argentina", "SA": "Saudi Arabia", "SE": "Sweden", "NL": "Netherlands", "CH": "Switzerland",
    "TR": "Turkey", "ID": "Indonesia", "TH": "Thailand", "MY": "Malaysia", "SG": "Singapore",
    "PH": "Philippines", "VN": "Vietnam", "NG": "Nigeria", "EG": "Egypt", "IL": "Israel",
    "AE": "United Arab Emirates", "HK": "Hong Kong", "PT": "Portugal", "PL": "Poland",
    "BE": "Belgium", "GR": "Greece", "NO": "Norway", "DK": "Denmark", "FI": "Finland", "AT": "Austria", "IE": "Ireland",
    "NZ": "New Zealand", "CL": "Chile", "CO": "Colombia", "PE": "Peru", "VE": "Venezuela",
    "CZ": "Czech Republic", "HU": "Hungary", "RO": "Romania", "PK": "Pakistan"
}

# 번역기 초기화
translator = Translator()

# Chrome WebDriver 경로를 지정하세요
driver_path = './chromedriver.exe'
service = Service(driver_path)

# Step 1: 웹페이지 열기
url = "https://www.trustpilot.com/review/binance.com?stars=1&stars=2&stars=3"
driver = webdriver.Chrome(service=service)
driver.get(url)

# 페이지가 로드되기를 기다림
time.sleep(5)

# 모든 리뷰 데이터를 저장할 리스트
all_data = []
review_number = 1  # 리뷰 번호 초기화

def scrape_page():
    global review_number  # 글로벌 변수로 설정하여 함수 내에서 접근 가능하게 함

    # 페이지 아래로 스크롤 (동적 로딩을 위해)
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(3)  # 스크롤 후 대기

    # 데이터 크롤링
    reviews = driver.find_elements(By.CSS_SELECTOR, 'section > div > article')

    for review in reviews:
        # 작성일자
        try:
            date_published = review.find_element(By.CSS_SELECTOR, 'time.typography_appearance-subtle__8_H2l').get_attribute('datetime').split("T")[0]
            year = int(date_published.split("-")[0])
        except:
            date_published = "Unknown"
            year = 0  # 기본값 설정

        # 최근 3년 데이터만 필터링
        if year >= 2022:
            # 아이디
            try:
                user_id = review.find_element(By.CSS_SELECTOR, 'aside > div > a > span').text.strip()
            except:
                user_id = "Unknown"

            # 국가 (코드 -> 국가명 변환)
            try:
                country_code = review.find_element(By.CSS_SELECTOR, 'aside > div > a > div > div > span').text.strip()
                country = country_mapping.get(country_code, country_code)  # 매핑된 국가명이 없으면 코드 그대로 사용
            except:
                country = "Unknown"

            # 내용
            try:
                content = review.find_element(By.CSS_SELECTOR, 'div.styles_reviewContent__0Q2Tg > p.typography_body-l__KUYFJ').text.strip()
                # 내용 번역
                content_translated = translator.translate(content, src='en', dest='ko').text
            except:
                content = "No content"
                content_translated = "번역 없음"

            # 별점 (data-service-review-rating 속성에서 숫자 추출)
            try:
                stars = review.find_element(By.CSS_SELECTOR, 'div.styles_reviewHeader__iU9Px').get_attribute('data-service-review-rating').strip()
            except:
                stars = "No rating"

            # 추천 수
            try:
                helpful_count = review.find_element(By.CSS_SELECTOR, 'div.styles_actionsWrapper__q1pnO > span:nth-child(1) > button > span > span > span').text.strip().split(" ")[0]
            except:
                helpful_count = "0"

            # 데이터 저장 (번호를 함께 추가)
            all_data.append([review_number, user_id, country, date_published, content, content_translated, stars, helpful_count])
            review_number += 1  # 다음 리뷰를 위해 번호 증가

# Step 2: 페이지 순회하면서 데이터 크롤링
while True:
    scrape_page()

    try:
        # 다음 페이지 버튼 클릭
        next_button = driver.find_element(By.CSS_SELECTOR, 'a[aria-label="Next page"]')
        next_button.click()
        time.sleep(5)  # 페이지 로드 대기
    except:
        # 다음 페이지 버튼이 없으면 종료
        print("더 이상 다음 페이지가 없습니다. 크롤링 종료.")
        break

# Step 3: 엑셀로 저장
df = pd.DataFrame(all_data, columns=["번호", "아이디", "국가", "작성일자", "내용", "번역 내용", "별점", "추천 수"])

# 오늘 날짜로 파일명 지정
today = datetime.today().strftime('%Y%m%d')
file_name = f"Trustpilot_review_{today}.xlsx"

# 엑셀로 저장
df.to_excel(file_name, index=False)

print(f"크롤링 완료. 파일 저장: {file_name}")

# 브라우저 닫기
driver.quit()


크롤링한 데이터


엑셀에 저장한 바이낸스 데이터를 시각화해 보자.

GPT에게 아래의 내용으로 분석을 요청했다.


요청 내용

전달한 파일 중 '내용' 부분을 NMF 분석방법으로 시각화해 줘 각 토픽별 자주 노출되는 키워드를 막대그래프로 빈도수를 확인하게 해줘야 해. 토픽 1~5까지 모든 토픽 그래프를 하나의 이미지를 이용해 노출해 주고 불용어와 'Binance'이라는 단어를 제외하고 키워드를 시각화해서 전달해 줘


결과

중요하지 않은 키워드를 중심으로 시각화자료 노출 

토픽 2의 내용을 보면 키워드 분석이 정상적으로 되지 않았음을 알 수 있다.



시각화한 토픽에 중요하지 않은 불용어들이 많이 포함되어 있었다.
따라서 리뷰 내용의 중요 텍스트를 GPT에 인지 시킨 후 이후에 시각화 자료를 요청하는 쪽이 시각화의 퀄리티를 높여줄 것이라 판단했다.


요청 내용

한국어로 내용을 전달해 주고 각 토픽별 주제에 대해 정리해 주면서 주요 불만사항들이 어떤 것들이 있었는지 알려줄래?


결과

토픽 1: 로그인 및 인증 관련 문제  

주요 키워드: logging, difficult, access, login, account

주요 불만사항: 로그인과 관련된 문제, 계정 접근이 어려워 불편을 겪는 사용자가 많았습니다. 인증 절차가 너무 복잡하거나, 로그인 시도가 자주 실패하는 등의 불만이 있었습니다.


토픽 2: 고객 지원 및 서비스 품질  

주요 키워드: support, customer, service, issue, help

주요 불만사항: 고객 지원의 반응 속도와 품질에 대한 불만이 많았습니다. 문제가 발생했을 때 고객 지원팀의 대응이 느리거나 해결되지 않는 경우가 많이 언급되었습니다.


토픽 3: P2P 거래 및 결제 관련 문제  

주요 키워드: p2p, transaction, payment, process, funds

주요 불만사항: P2P 거래 및 결제 과정에서 발생하는 문제에 대한 불만이 많았습니다. 특히 자금 이체 지연이나 결제 실패와 같은 문제가 자주 발생하는 것으로 나타났습니다.


토픽 4: 사기 의혹 및 신뢰 문제  

주요 키워드: fake, company, scam, fraud, trust

주요 불만사항: Binance에 대한 신뢰가 떨어진다는 의견과 사기 또는 사기 회사라는 의혹을 제기하는 사용자들이 있었습니다. 플랫폼의 투명성이나 신뢰성에 의문을 가지는 리뷰가 포함되었습니다.


토픽 5: 거래 및 수수료 문제  

주요 키워드: trade, fees, withdrawal, deposit, high

주요 불만사항: 거래 과정에서 발생하는 높은 수수료와 출금, 입금 관련 문제에 대한 불만이 주로 제기되었습니다. 특히 거래 수수료가 예상보다 높거나 출금 절차가 지연되는 등의 문제들이 지적되었습니다.



각 키워드들이 주요 키워드인지 확인하기 위해 각 키워드 노출 빈도 수와 내용을 표로 정리해 달라고 했다.

요청 내용

토픽 1: 로그인 및 인증 관련 문제
토픽 2: 고객 지원 및 서비스 품질
토픽 3: P2P 거래 및 결제 관련 문제
토픽 4: 사기 의혹 및 신뢰 문제
토픽 5: 거래 및 수수료 문제

해당 내용의 불만사항들과 각 토픽별 많이 언급된 키워드 5개씩, 그리고 각 키워드의 언급 수를 도표로 정리해서 전달해 줘


결과


요청 내용

그럼 다시 NMF 방식으로 시각화해 볼까?


결과


요청 내용

그렇다면 이제 각 토픽별 페인포인트들과 개선할 수 있는 점들에 대해 도표로 정리해 줄래?


결과


사용해 본 총평

 별다른 코딩 지식 없이도 데이터를 수집하고 시각화할 수 있다는 점에서 Chat GPT 4o는 너무나 훌륭한 툴이라고 생각한다. GPT에 100% 의존해서는 안 되겠지만 방향성을 잡아가는 데에는 확실한 도움이 될 것 같다.


chat GPT를 이용하기 이전에도 데이터 수집을 위해 종종 파이썬을 이용해 본 경험이 있다. 구글에서 떠 돌아다니는 사람들의 코드 덕분에 데이터를 크롤링할 수 있었는데 Chat GPT를 이용해 보니 쉽고 빠르게 이용이 가능했다.


물론 파이썬 사용 경험이 없다면 수집하고자 하는 부분을 찾아 GPT에게 알려주는 부분이 어려울 수 있지만 이 부분은 F12 버튼을 눌러 개발자 모드를 열어서 확인할 수 있다.

https://saint-story.tistory.com/18

결과적으로는 AI에 의존해 사용자 페인 포인트를 분석하는 것은 신뢰도가 떨어질 수 있겠다고 느꼈다. AI 기술이 많이 개선되었다고 하지만 AI가 만들어내는 데이터에는 할루시네이션이 포함될 가능성이 존재하기 때문이다.

https://cloud.google.com/discover/what-are-ai-hallucinations?hl=ko


특히 사용했던 키워드 노출 빈도수 같은 경우 일치하는 것도 있었지만 정말 다르게 카운트하고 있는 데이터들도 존재했다. 

(*엑셀에서 P2P 키워드 조회 시 '137', GPT  '0')


특히 도표에 노출된 정보를 보면 정량화된 내용을 볼 수 없다. 그럴듯한 워딩으로 잘 포장한 문장이다. 고객 지원이 느리다고 한 기간이 평균 어느 정도인지, 높다고 느낀 수수료 금액과 인출에 걸리는 시간 등 구체적인 내용을 파악하는 데에는 무리가 있다.


이런 데이터로는 어떠한 의사 결정도 할 수 없다.


따라서 실무에서 사용할 때에는 엑셀을 이용해서 해당 데이터 값이 올바른 것인지 검증이 필요하다 느꼈고 정량적인 데이터 추출을 하기 위해 GPT를 더욱 공부해야겠다는 생각이 들었다.


확인해 본 것처럼 기존 여러 툴과 AI가 결합해 더 나은 생산성을 제공하는 시대가 빠르게 찾아올 것이라고 생각한다. AI를 활용할 수 있는 사람의 수준의 차이에 따라 결과물의 '수준'은 비교할 수 없을 것이다.


역시 'AI'도 보여지는 속도와 생산성보다는 결국 다룰 줄 아는 사람의 '퀄리티'가 중요했다. 


기교보다 기본이다


꾸준히 그리고 많이 배워야겠다는 생각이 든다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari