반응형

전편 [R 네이버 영화 웹 크롤링하기 #1] 에 이어서 내용 계속하도록 하겠습니다.

너무 오랜만에 코드를 보니까 남이 짠 것 코드를 보는 것 마냥 새롭네요..ㅎ

전 내용에서는 '네이버 영화 랭킹 페이지'에서 1위부터 100위까지의 영화 목록을 수집했었습니다.

 


혹시 가공하지 않은 영화 리뷰에 대한 데이터가 필요하시다면 아래 게시글로 들어가주세요.

 [R 네이버 영화 웹 크롤링하기 #3 - [번외] 영화 리뷰 수집]

이번 게시글에서는 리뷰를 수집하여 가공하는 작업이 있습니다!

리뷰만 수집하시려는 분들에게는 불필요한 내용이 있어요!


 

이번 내용에서는 수집한 2000개의 영화에 등록된 리뷰과 평점, 특정 키워드 건수을 읽어들이겠습니다.

페이지 별로 URL의 형식이나, HTML이 구성되는 방식이 다르니까 변수 선언부터 차근차근 봐주시기 바랍니다^^

아마 페이지별로 담당 개발자분이 달라서 개발 스타일로 다른 것 같네요.

 

저는 2 건 이상의 영화에 대해서 리뷰를 수집하는 것이니,

하나의 영화에 대해서 리뷰를 수집하는 경우 배열의 형식이나 for 문을 돌릴 필요가 없을 수 있습니다^^

 

쇼생크 탈출(영화)의 경우만 봐도 리뷰가 약 1만 6천개 등록되어 있습니다.

저는 2000개의 영화에 대한 모든 리뷰가 필요한 것이 아니라 '특정 키워드'가 포함된 리뷰의 건수를 구하였으니

필요에 따라 코드를 수정하시기 바랍니다.

 

시작!

 


 

지금부터 크롤링 할 페이지는 리뷰 페이지!

빨간 네모 부분이 네티즌이 영화에 대해 작성한 리뷰와 평점 페이지입니다.

 

음.. 저도 웹과 HTML에 익숙하지 않아 페이지라는 것이 정확한 표현인지는 모르겠지만..

눈으로 보이는 웹 페이지는 사실 1개 이상의 여러 개의 페이지로 구성되어 있다고 생각하시면 됩니다.

아래 빨간 네모는 '쇼생크 탈출 영화 정보'라는 큰 틀에서 리뷰와 평점에 대한 페이지만 색칠한 거에요. 

 

 

 


 

시작 전에 [R 네이버 영화 웹 크롤링하기 #1]에서 생성한 텍스트 파일(아래 사진)이 존재해야합니다^^

텍스트 파일을 직접 수정하실 경우 열의 위치, 데이터 형식에 주의해주시길 바랍니다.

 

 

 


 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#+--------------------------------------------------------------------------------------------+#
# 제 목 : 네이버 영화 상세 페이지에서 영화별 리뷰를 가져온다.
# 작성자 : 2015013390
# 작성일 : 2017-06-11
# 입력값 : [1_네이버 영화 평점 목록 크롤링] 스크립트 실행 후 결과 파일을 엑셀로 데이터 정리 후 txt(탭으로 구분)으로 만들어서
#        code-영화고유코드값, movie-영화이름으로 매핑해야 함
# 파일위치 : C:\Temp
# 소요시간 : 270개의 영화 파일 리뷰 읽어들이는 데에 12시간 이상 소요되서 총 소요시간은 모름^^ㅎ;;..
#           맥북 + R 언어 + 한글 + 내 코딩의 조합이 성능에 엄청난 영향을 준 듯.. 
#           크롤링한 리뷰와 평점 데이터는 최소 20만 건 정도 되는 듯 하다.
#+--------------------------------------------------------------------------------------------+#
 
library(XML)
library(stringr)
 
#크롤링 시작#
url_base <- "http://movie.naver.com/movie/bi/mi/pointWriteFormList.nhn?code=" #네이버 영화 상세 리뷰 1
url_paging <- "&type=after&isActualPointWriteExecute=false&isMileageSubscriptionAlready=false&isMileageSubscriptionReject=false&page=" #네이버 영화 상세 리뷰 2
 
all.review_cnt <- c() #영화 리뷰 건수
all.keyword_cnt <- c() #영화 리뷰 중 특정 키워드가 인용된 건수 
                       #(ex:영화 쇼생크탈출 리뷰 16350 건 중 '최고'이라는 키워드가 3392 번 사용되었다.)
                       
keyword <- '최고' #특정 키워드 지정
cs

 

line 17 : 영화 리뷰 URL 첫번째

line 18 : 영화 리뷰 URL 두번째

하나의 URL을 매개변수 입력을 위해 두 개로 나누어 놓은 것이니 URL1, URL2로 생각하면 된다.

 

line 20 : 한 영화에 대해 리뷰가 몇 건 작성되었는지 기록할 리스트

line 21 : 작성 된 리뷰 중 특정 키워드(ex - 최고, 존잼)이 인용된 건 수

line 24 : 특정 키워드

 

 


 

 

1
2
3
4
5
6
7
8
#------------------------------------------------------------------------
#크롤링할 영화 목록 파일 불러오기
#------------------------------------------------------------------------
#target_file <- read.csv("C:\\Temp\\movie_list.txt", header=T)
target_file <- read.csv(file.choose(), header=T, sep=" ")
 
success_cnt <- 0 #정보 확인한 영화 건 수
start_movie <- 1
cs

 

line 4 : 주석

line 5 : 영화 목록 text파일을 직접 선택한다. header=T : 헤더파일이 존재하니 두번째 행 부터 데이터라는 뜻.

 

line 7 : 이 부분은 웹크롤링을 20만 건 정도 하다가 발견된 문제를 보완해주기 위해 넣은 겁니다.

시간이 너무 오래 걸려서 중간에 끊으니까 지금까지 크롤링 한 데이터까지 모두 날라가더라구요.

크롤링을 중간에 멈추더라도, 그 전까지의 정보를 저장하고자 추가한 체크 변수입니다.

크롤링 데이터가 5 만 건 이하라면 생락하셔도 됩니다. (있어도 상관은 없구엽..)

line 8 : 위와 같은 문제로 추가한 변수

 


이제부터 엄청 기니까 잘 따라오셔야 해요!

 

★당부드릴 말씀★

저는 수 십만개의 리뷰 내용이 모두 필요한 것이 아니라,

특정 키워드가 포함된 리뷰가 몇 건인지를 알아내는 것이 목적이었기 때문에 all.reviews에 담긴 리뷰 데이터를 가공하여 사용하였습니다.

영화의 리뷰 내용 자체를 크롤링하셔야 하는 분들은 아래부터 소스부터 로직을 꼭 이해하셔서 수정하셔야 합니다.

txt파일의 컬럼(열) 위치와 내용, 데이터 형식, 변수 형식에 유의하여 변경하시기 바랍니다

 

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#------------------------------------------------------------------------
#크롤링 시작 : 영화별로 리뷰건수와 리뷰내용을 크롤링한다
#------------------------------------------------------------------------
for(i in start_movie:2000)
{
    movie_code <- target_file$code[i]
    
    #------------------------------------------------------------------------
    #영화 리뷰건수 크롤링
    #------------------------------------------------------------------------
    #i #print
    url_main <- paste(url_base, movie_code, sep='') #네이버에서 관리하는 영화 고유코드값
    url_main <- paste(url_main, url_paging, sep='')
    url_main <- paste(url_main, 1, sep='')
    
    txt <- readLines(url_main, encoding="UTF-8") #웹 크롤링
    
    #div total 클래스 아래에 리뷰 총 건수가 있다.
    review_cnt <- txt[which(str_detect(txt, "class=\"total\""))]
    review_cnt <- str_replace(review_cnt,"140자 평","")
    review_cnt <- gsub("\\D","",review_cnt) #숫자를 제외한 문자 제거
 
    if( review_cnt == 0 | length(review_cnt) == 0 )
    {
        review_cnt<-0
        all.review_cnt <- c(all.review_cnt, review_cnt) #리뷰 건수 저장
        break
    }
    
    all.review_cnt <- c(all.review_cnt, review_cnt) #리뷰 건수 저장
    
    #반복할 리뷰 페이징 건수
    if( review_cnt > 10 | length(review_cnt) > 1)
    {
        #페이지마다 리뷰가 10건 씩 반복되니, 총리뷰건수/10 하면 최종 페이지가 나옴
        total_page <- as.numeric(review_cnt) %/10  #review_cnt%/%10 이렇게 쓰면 이항연산자에 수치가 아닌 인수입니다. 라는 에러가 발생함 
    } else
    {
        total_page <- 1
    }
    
    all.reviews <- c() #영화 리뷰
    
    #------------------------------------------------------------------------
    # 영화 리뷰 내용 크롤링
    #------------------------------------------------------------------------
    for(page in 1:total_page) #1 to total_page
    {
        #page #print
        url_sub <- paste(url_base, movie_code, sep='') #영화 리뷰 url
        url_sub <- paste(url_sub, url_paging, sep='')
        url_sub <- paste(url_sub, page, sep='') #영화 상세 리뷰 페이징
        
        review_txt <- readLines(url_sub, encoding="UTF-8") #웹 크롤링
         
        reviews <- review_txt[which(str_detect(review_txt, "class=\"score_reple\""))+1] #div score_reple 클래스 아래에 리뷰가 있다.
         reviews <- c(str_match(reviews , keyword)) # 특정 키워드가 포함된 리뷰만 저장, 아닌것은 NA 로 !!!!!
        
        all.reviews <- c(all.reviews, reviews) #리뷰 목록 저장
    }
        
    #------------------------------------------------------------------------
    # 영화 리뷰 내용 크롤링 후, 해당 영화의 리뷰에서 특정 단어가 몇 번이나 인용되었는지 카운트
    #------------------------------------------------------------------------
    keyword_cnt <- all.reviews[!is.na(all.reviews)]
    keyword_cnt <- length(keyword_cnt)
    all.keyword_cnt <- c(all.keyword_cnt, keyword_cnt)
    
    success_cnt <- success_cnt + 1
}
 
cs

 

line 4 : 2000개의 영화에 대한 리뷰를 수집하기 위해 반복문 사용.

하나의 영화만 하실거면 for 문은 사용하지 않으셔도 됩니다.

 

line  6 : 앞서 불러들인 영화목록 txt파일에서 code 컬럼(열)의 i 번째 데이터를 movie_code 변수에 입력한다.

 

line 12 : 영화 리뷰 페이지 URL에 검색할 영화의 코드를 입력한다.

line 13 : 영화 리뷰 페이지 URL 뒷 부분을 입력한다.

line 14 : 리뷰 페이지 페이징 처리한다. (반복부)

 

[ URL 예시 ]

http://movie.naver.com/movie/bi/mi/pointWriteFormList.nhn?code=17421&type=after&isActualPointWriteExecute=false&isMileageSubscriptionAlready=false&isMileageSubscriptionReject=false&page=1

파란색 부분 : line 12 - URL 첫부분 + 5자리의 영화 코드

검은색 부분 : line 13 - URL 뒷부분

빨간색 부분 : line 14 - 리뷰페이지 1부터 ~ 끝까지 페이징처리(반복)를 하면서 데이터를 얻기 위함

 

 

line 16 : url 변수에 조합한 URL 정보를 긁어온다. 인코딩 형식은 UTF-8로 한다.

인코딩 형식은 페이지 마다 다른데, 보통 UTF-8이나 euc-kr이 일반적입니다.

크롬-개발자도구를 통해 소스를 보면 페이지 인코딩이 어떤 형식으로 되어있는지 볼 수 있습니다.

 

line 19 : 리뷰 페이지 소스코드를 분석해보니 class=\"total\" 에 해당 영화에 대한 '총 리뷰 건 수'가 존재하네요.

str_detect 함수를 이용하여 class=\"total\" 문자열을 찾아서 관련 내용을 review_cnt 변수에 넣어줍니다.

 

line 20 : 앗! review_cnt 변수에 불필요한 한글까지 포함되어 있네요.

총 건수만 가져오면 되니까 '140자 평'이라는 글자를 제거해줍니다.

 

line 21 : 숫자를 제외한 문자를 모두 제거합니다. 그러면 해당 영화에 대한 총 건수만 존재하게 된답니당.

line 23 : 예외 처리 부분

line 30 : review_cnt 변수를 all.review_cnt (배열 개념의 변수)에 넣어줍니다.

line 33 : 총 리뷰건수 / 10을 하면 리뷰가 몇 페이지가 존재하는지 알 수 있습니다.

line 42 : all.reviews 변수 초기화

 

line 47 : 본격적으로 영화 리뷰 크롤링 시작하는 부분ㅋ

line 54 : 10 건의 리뷰가 존재하는 페이지 정보를 크롤링 해온다.

line 56 : 리뷰 상세 페이지를 분석해보니 class=\"score_reple\" 에 리뷰 정보가 존재하네요! 이 부분을 가져오면 되겠죠?

line 57 : 이 부분은 제외하시기 바랍니다. 특정 키워드가 포함되지 않은 리뷰는 제거하는 로직입니다.

line 59 : 읽어들인 10개의 리뷰를 all.reviews 변수에 저장한다.

line 65 : all.reviews 변수에서 null 값 제거

 


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#------------------------------------------------------------------------
#출력파일 만들기
#------------------------------------------------------------------------
 
#만약 실행 도중 취소했다면 아래 로직 수행하기
#success_cnt <- success_cnt + 1
 
lv_from <-start_movie
lv_to <- start_movie+success_cnt
<- target_file[lv_from:lv_to, ]
#x <- head(target_file, n=success_cnt)
<- cbind(x,head(all.review_cnt,n=success_cnt)) #영화 리뷰 건수 추가
<- cbind(x,head(all.keyword_cnt,n=success_cnt)) #특정 키워드가 인용된 건수 추가
 
 
colnames(x) <- c("code","movie_title","point","review_cnt","keyword_cnt")
 
write.table(x, "C:\\Temp\\final_list.txt")
cs

 

line 6 : 위에서 언급했듯이 for문을 돌리다가 중간에 취소하였을 경우, 이전까지의 데이터를 복원하기 위함입니다.

line 8 : 위와 동일

line 9 : 위와 동일

line 10 : 위와 동일

line 11 : 주석

line 12 : 맨 처음 불러들인 영화목록 txt파일에 각 영화별 리뷰 총 건수를 추가한다.

line 13 : 영화목록 txt파일에 특정 키워드가 인용된 건수를 추가한다.

 

line 16 : 추가한 두 컬럼(열)의 컬럼명을 지정한다.

 

line 18 : 결과 파일을 txt파일로 만든다.

 


 

드디어 끝났네요!

1위부터 270위까지의 영화 리뷰를 읽어들이는 데에만 12시간이 넘게 소요되서 중간에 멈췄네요ㅎㅎ

 

여튼 [R 네이버 영화 웹 크롤링하기 #1] 에서 생성한 movie_list.txt 파일에서

각 영화별 리뷰 정보를 읽어들여 가공한 결과를 추가하여 우측 final_list.txt로 생성하였습니다.

 

 

 

좋은 하루 되세요ㅎㅎ~

 

 

 

 

반응형