# from selenium import webdriver
# from selenium.webdriver.common.by import By
# from selenium.webdriver.support.ui import WebDriverWait
# from selenium.webdriver.support import expected_conditions as EC
# import pandas as pd
# import openpyxl
# import time
#
# def collect_article_content():
# try:
# main_element = WebDriverWait(driver, 10).until(
# EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/div/div/div[2]/div[2]/div[2]/div/div/div/div/div'))
# )
# return main_element.get_attribute('innerText')
# except:
# try:
# main_element = WebDriverWait(driver, 10).until(
# EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/div/div/div[2]/div[2]/div[1]/div/div/div'))
# )
# return main_element.get_attribute('innerText')
# except:
# return None
#
# # 크롬 드라이버 실행
# driver = webdriver.Chrome()
#
# url = "카페 페이지 url을 입력하세요"
# driver.get(url)
# time.sleep(3)
#
# # 로그인 - 시간 내 직접하는 방식
# time.sleep(12)
#
# # 로그인 완료 후 다시 카페 페이지로 이동
# driver.get(url)
# time.sleep(3)
#
# try:
# # 텍스트가 있는 iframe으로 전환
# element = WebDriverWait(driver, 20).until(
# EC.presence_of_element_located((By.ID, "cafe_main"))
# )
# driver.switch_to.frame(element)
#
# # 모든 텍스트 수집
# all_text = collect_article_content()
# df = pd.DataFrame([all_text], columns=['content'])
# df.to_excel('저장할 파일명.xlsx', index=False, engine='openpyxl')
#
# except Exception as e:
# print(f"An error occurred: {e}")
#
# finally:
# driver.quit()
크롤러는 vscode-python을 사용하여 제작했습니다.
카페 글 중 로그인을 해야 볼 수 있는 글과 전체 공개 글의 XPATH가 달라서 두 가지 모두 보도록 설정했습니다. 해당 XPATH경로는 언제든 바뀔 수 있습니다.
시간상 간단히 만든 크롤러라 로그인은 직접하는 방식으로 설정했고, 타자 속도에 따라 로그인 시간은 조정할 필요가 있습니다. 또한 글의 본문에 있는 모든 텍스트를 수집하도록 설정하였기에 동영상이 있는 경우 ‘동영상’, ‘재생’ 등의 단어도 함께 수집될 수 있습니다(코드 수정 혹은 전처리가 필요합니다). 저의 경우 텍스트마이닝을 하며 전처리도 했고, 빈도분석이나 tf-idf에서 걸러질 것으로 보아 그냥 두었습니다.
네이버 카페는 마우스로 긁어서 복사가 안되는 경우가 있는데, iframe으로 이동 후 텍스트를 수집하면 잘 됩니다.
folder_path <- "크롤링 한 xlsx파일들이 존재하는 폴더 경로를 입력해주세요"
file_list <- list.files(path = folder_path, pattern = "*.xlsx", full.names = TRUE)
data_list <- lapply(file_list, function(file) {
read_excel(file)
})
result_df <- bind_rows(data_list)
result_df
저는 네이버 카페 중 ’클라이밍’카페를 예시로 크롤링했습니다. 모든 xlsx파일을 읽어와서 하나의 df로 정리하는 과정입니다. 크롤링한 파일 형태에 따라 조금씩 수정될 수 있습니다.
clean_text <- function(x) {
str_trim(str_replace_all(x, "\n", " "))
}
dt_pp <- result_df %>%
mutate(across(everything(), ~ clean_text(.)))
dt_pp
모든 줄넘김을 공백 한 칸으로 대체하는 함수를 만들고 모든 값에 적용했습니다.
pre_dt <- dt_pp$content %>%
str_replace_all('[^가-힣]', ' ') %>%
str_squish() %>%
as_tibble() %>%
filter(value != "")
token_dt <- pre_dt %>%
unnest_tokens(input = value,
output = word,
token = extractNoun)
token_dt <- token_dt %>%
filter(!word %in% c("재생", "해서", "너무", "들이", "서울특별시", "부산", "사진", "영상", "이번", "하시", "하기", "비슷",
"여기", "장님", "만원", "하면", "강남", "클라이밍을", "오버", "다이", "서울", "일산", "재밌게", "마곡",
"마지막", "얼마", "오랜만", "하루", "논현", "어제", "카페", "홍대"))
token_dt <- token_dt %>%
count(word, sort = T) %>%
filter(str_count(word) > 1) %>%
filter(n >= 20)
token_dt
저는 클라이밍 카페를 예시로 크롤링했기 때문에 다음과 같은 결과를 얻었습니다.
기본적인 한글 전처리를 하고 토크나이징을 진행했고, 불용어를 제거했습니다. 필요에 따라 지역과 관련된 단어도 제거하였습니다.
클라이밍은 경로를 ’문제’라는 단어로 사용하는 것을 알 수 있었습니다. 또한 암장의 종류도 (지구력, 볼더링, 스트레칭, 트레이닝, 리드, 빌레이 등) 다양하게 존재하는 것으로 보입니다. 난이도는 주로 색상으로 나타납니다(주로 흰색~붉은 색 또는 어두운 색). 유저들이 주로 신경쓰는 요소는 (공간, 사람, 주차 시설, 샤워 시설, 탈의실, 세족실) 정도로 보입니다. 유저들은 타 지역에 갈 때 ’원정’이라고 하고 본인 지역에서 주로 가는 곳을 ’홈짐’이라고 합니다. 또한 새로 오픈하는 클라이밍장을 오픈런 하는 경향도 보였습니다.
마찬가지로 적당히 전처리를 하고, 각각의 글마다 id를 부여하여 하나의 글에서 함께 사용되는 단어를 살펴보았습니다. 당연하게도 빈도분석과 비슷한 결과를 보였으나, 링크의 짙은 정도를 통해 그 빈도를 볼 수 있었습니다.
다음은 n-gram 분석도 해보았습니다. 이 이미지는 앞선 pairwise와는 달리, 모든 글에서 붙어서 나타나는 단어를 분석한 것입니다. 역시 빈도가 높은 경우로 필터링하였습니다. 후기 글이므로 주로 센터 이름들이 많이 나타나고 있습니다. 빈도분석에서 본 것처럼 난이도와 관련된 색깔 단어도 눈에 띄고, 새로 오픈한 곳을 다녀온 후기도 많았다는 것을 알 수 있었습니다.