study blog

Crawling & Scraping을 이용한 데이터 구축 - 네이버 영화 댓글, rotten tomatoes 본문

R/2. 데이터 구축

Crawling & Scraping을 이용한 데이터 구축 - 네이버 영화 댓글, rotten tomatoes

ivo_lee 2020. 1. 10. 16:54

Crawling & Scraping을 이용한 데이터 구축

- 특정 사이트에 접속해서 원하는 데이터 추출하기

데이터 수집 방식: 클라이언트가 request를 보냄 → 요청을 서버프로그램이 받음
→ 서버프로그램이 결과 html 페이지를 생성해서 client에게 response로 전달
→ 클라이언트는 selector와 xpath를 이용해서 전달된 HTML 내에 있는 필요한 데이터를 추출

 

용어에 대해 알아보자! 

- web crawling : 인터넷 상에서 필요한 정보를 읽어와서 수집하는 일련의 작업(과정)

- web scraping : 하나의 web page에서 내가 원하는 부분을 추출하는 행위

- web crawling(web spidering) : 자동화 봇인 crawler가 정해진 규칙에 따라 복수개의 web page를 browsing하는 행위

- scraping을 할 때 CSS(jQuery) selector를 이용해서 필요한 정보를 추출

- 추가적으로 xpath도 이용해보자! (selector와 하는 일은 동일-원하는 위치 지정)  xml기반의 다른 표현임.

 


예제 1. naver 영화댓글 크롤링

방법 1) selector를 이용한 자료 처리

1-1) 서버로부터 받은 html 태그로 구성된 문자열을 자료구조화 시키는 패키지를 이용해야 함

install.packages("rvest")
library(rvest)
library(stringr)

1-2) url 준비

url <- "https://movie.naver.com/movie/point/af/list.nhn"
page <- "page="
request_url <-str_c(url,"?",page,1)    # 서버쪽에 내가 요청할 주소
# crawling하려면 page,1을 for문 돌리면 됨!

1-3) 준비된 url로 서버에 접속해서 html을 읽어온 후 자료구조화 시킴

html_page <- read_html(request_url)
# class(html_page)

1-4) selector를 이용해서 추출하기 원하는 요소(element)를 선택

# html_nodes: 원하는 element 찾아오고싶을때
nodes = html_nodes(html_page,         # 찾아올 위치
                   "td.title>a.movie"  # td중 class:title 의 자식인 a중 class:movie
)

1-5) tag 사이에 들어있는 text를 추출

title <- html_text(nodes, trim=T)   # node.text() : 이건 jQuery에서 사용
# html_text: 태그사이의 글자 가져옴

1-6) selector를 이용해서 리뷰 요소(element)를 선택  

nodes2 = html_nodes(html_page,"td.title")
review <- html_text(nodes2, trim=T)          #trim=T: 앞뒤공백 제거
class(review)                               #txt: 다 character로 구성된 vector

1-7) 필요없는 문자들을 제거

review = str_remove_all(review,"\t")     # 특정 패턴에 맞는 내용 삭제해줌
review = str_remove_all(review,"\n")
review = str_remove_all(review,"신고")  # 마지막 신고만 지워야하는데 일단 이렇게 함
# txt = str_remove_all(review,title)    # 댓글 내용 중 제목이 있어도 사라짐

1-8) 영화 제목과 리뷰에 대한 내용을 추출

df = cbind(title,review)
View(df)

방법 2) xPath를 이용한 자료 처리

install.packages("rvest")
library(rvest)
library(stringr)

url <- "https://movie.naver.com/movie/point/af/list.nhn"
page <- "page="
request_url <-str_c(url,"?",page,1) 
html_page <- read_html(request_url)
nodes = html_nodes(html_page, "td.title>a.movie")
title <- html_text(nodes, trim=T)

#review 부분은 xpath로 가져와 보자!
nodes2 = html_nodes(html_page,
                    xpath='//*[@id="old_content"]/table/tbody/tr[1]/td[2]/text()')

# xpath 복사하면 //*[@id="old_content"]/table/tbody/tr[1]/td[2]/text()
# '로 써주기 (“쓰면 겹치는 부분 있으니까)

review <- html_text(nodes2, trim=T)  # -> review하나만 뽑기
review[3]!  # -> review 여러개 뽑기
review=vector(mode="character",length=10);

for(idx in 1:10){
  myPath = str_c('//*[@id="old_content"]/table/tbody/tr[',idx,']/td[2]/text()')
  nodes3 = html_nodes(html_page, xpath=myPath)
  txt <- html_text(nodes3, trim=T)
  review[idx] <- txt[3]
}

df = cbind(title,review)
View(df)

 

[연습문제 1] 함수 만들기 : 해당 페이지의 영화제목, 리뷰를 출력하는 함수를 만들어보자.

extract_comment = function(idx){
  url <- "https://movie.naver.com/movie/point/af/list.nhn"
  page <- "page="
  request_url <-str_c(url,"?",page,idx)
  html_page <- read_html(request_url, encoding="CP949")

  nodes = html_nodes(html_page, "td.title>a.movie")
  title <- html_text(nodes, trim=T)

  review=vector(mode="character",length=10);
  for(idx2 in 1:10){
    myPath = str_c('//*[@id="old_content"]/table/tbody/tr[',idx2,']/td[2]/text()')
    nodes3 = html_nodes(html_page, xpath=myPath)
    txt <- html_text(nodes3, trim=T)
    review[idx2] <- txt[3]
  }

  df = cbind(title,review)
  return(df)
}

# 함수를 호출해서 crawling해보기!
result_df = data.frame();
for(i in 1:10){
  tmp <- extract_comment(i)
  result_df <- rbind(result_df,tmp)
}

 

[연습문제 2]

install.packages("jsonlite")    #json처리하는데 많이 사용하는 패키지
install.packages("httr")        #network 사용하는데 필요한 패키지들
install.packages("stringr")
install.packages("rvest")
library(rvest)
library(jsonlite)
library(httr)
library(stringr)

extract_comment = function(idx){
  url1 <- "https://www.rottentomatoes.com/top/bestofrt/?year=2019"
  html_page <- read_html(url1)  #encoding="CP949"
  nodes = html_nodes(html_page,"td>a.unstyled.articleLink")
  # xpath 사용할 때  //*[@id="top_movies_main"]/div/table/tr[1]/td[3]/a  

  link = html_attr(nodes,"href")
  title = html_text(nodes,trim=T)

  url2 <- "https://www.rottentomatoes.com"
  request_url <- str_c(url2,link[idx])
  html_page2 <- read_html(request_url)  #encoding="CP949"
  #nodes2 = html_nodes(html_page2,"div.meta-value")
  #html_text(nodes2)
  #nodes2 = html_nodes(html_page2,
  #                    xpath='//*[@id="mainColumn"]/section[4]/div/div/ul/li[1]/div[2]/text()')
  
  #//*[@id="mainColumn"]/section[4]/div/div/ul/li[1]  # rating 줄 전체
  #//*[@id="mainColumn"]/section[4]/div/div/ul/li[1]/div[2]
  #//*[@id="mainColumn"]/section[4]/div/div/ul/li[2] # 장르줄 전체
  #topSection > div.col-sm-17.col-xs-24.score-panel-wrap > div.mop-ratings-wrap.score_panel.js-mop-ratings-wrap > section > section > 

  nodes2 = html_nodes(html_page2,"div > strong.mop-ratings-wrap__text--small")

  user_rating = html_text(nodes2[2])
  user_rating = str_remove(user_rating,"User Ratings: ")
  user_rating = str_remove_all(user_rating,",")
  user_rating = as.numeric(user_rating)

  nodes3 = html_nodes(html_page2,"section.panel.panel-rt.panel-box.movie_info.media>div>div>ul>li:nth-child(2)>div.meta-value>a")
  #nodes3 = html_nodes(html_page2,"div.meta-value>a")
  #html_attr(nodes3,"href")

  genre <- html_text(nodes3)
  #txt<- html_text(nodes3)
  #genre[idx] <- txt[] 

  df = cbind(title,user_rating,genre)
  return(df)
}


# 함수를 호출해서 crawling해보기!

result_df = data.frame();

for(i in 1:10){
  tmp <- extract_comment(i)
  result_df <- rbind(result_df,tmp)
}

#sq <- seq(max(length(n),length(s)))
#data.frame(n[sq], s[sq])


예제 2. rotten tomatoes 크롤링

install.packages("jsonlite")    #json처리하는데 많이 사용하는 패키지
install.packages("stringr")
install.packages("rvest")
library(rvest)
library(jsonlite)
library(stringr)

extract_comment = function(idx){
  url1 <- "https://www.rottentomatoes.com/top/bestofrt/?year=2019"
  html_page <- read_html(url1)  #encoding="CP949"
  nodes = html_nodes(html_page,"td>a.unstyled.articleLink")

  link = html_attr(nodes,"href")
  title = html_text(nodes,trim=T)

  url2 <- "https://www.rottentomatoes.com"
  request_url <- str_c(url2,link[idx])
  html_page2 <- read_html(request_url)

  nodes2 = html_nodes(html_page2,"div.mop-ratings-wrap__half.audience-score>h2>a>span.mop-ratings-wrap__percentage")
  user_rating = html_text(nodes2, trim=T)

  nodes3 = html_nodes(html_page2,"section.panel.panel-rt.panel-box.movie_info.media>div>div>ul>li:nth-child(2)>div.meta-value>a")
  genre <- html_text(nodes3)

  #1.
  #myList[[idx]] <- list(title[idx],user_rating,genre)
  #return(myList)
  
  #2. 
  # df = cbind(title=title[idx],user_rating,genre)

  #3.
  df = cbind(title=title[idx],user_rating)
  for(i in 1:length(genre)){
    df <- cbind(df,genre=genre[i])
  }
  #return(df)

  l <- list(title[idx],user_rating,genre)
  max.length <- max(sapply(l,length))

  l <- lapply(l,function(v){c(v, rep(NA, max.length-length(v)))})
  df2<- do.call(rbind,l)

  return(df2)
}

 
# 함수를 호출해서 crawling해보기!

# 1. 
result_df = data.frame();
for(i in 1:10){
  tmp <- extract_comment(i)
  result_df <- rbind(result_df,tmp)
}

#df = cbind(title=title[idx],user_rating)
#for(i in 1:length(genre)){
#  df <- cbind(df,genre=genre[i])
#}
#return(df)

# 2. 
result_df = data.frame();
tmp=list();
for(i in 1:3){
  tmp <- extract_comment(i)
  result_df <- list(result_df,tmp)
}

# 3.
result_df = data.frame();
for(i in 1:10){
  tmp <- extract_comment(i)
  maxSeq <- seq(max(result_df[i,],tmp))
  result_df <- rbind(result_df[maxSeq],tmp[maxSeq])
}

 

 

 

 

 

'R > 2. 데이터 구축' 카테고리의 다른 글

selenium을 이용한 동적 page 데이터 추출  (0) 2020.01.14
Comments