본문 바로가기

R

[R] 크롤링, 스크래핑

크롤링(crawling)
: 자동화된 방법으로 웹을 탐색하는 컴퓨터프로그램
인터넷 사이트의 웹페이지를 수집해서 분류하는 프로그램

스크래핑(scraping)
: 웹브라우저 화면에 표시되는 html 문서에서 사용자가 필요한 정보만 추출하여 수집하는 기술

1. 사용자가 웹브라우저의 주소창에서 url을 직접 입력한다.
2. request : 웹브라우저는 요청한 메세지를 작성해 웹서버로 전송한다.
3. response : 웹서버는 요청받은 정보를 클라이언트에게 보낸다.(HTML)
4. 웹브라우저는 응답메세지를 해석해 사용자에게 정보를 출력한다.

 

install.packages("rvest")
library(rvest)
html <- rvest::read_html("https://www.joongang.co.kr/article/25045987")
#read_html : R에서 주소로 request 보내고 response 받을 수 있는 함수

str_extract(html,'<title>.+</title>') #처음에 나온 하나만 출력
str_extract_all(html,'<title>.+</title>') #전부 출력

html_nodes(html,'h1')%>%
  html_text()#태그정보 제외하고 text만 출력

F12 화면에서

id = #

class = .

 

조선일보 기사 웹 스크래핑 하기

1) 특정한 뉴스 기사 검색의 url 수집

html <- rvest::read_html("https://www.joongang.co.kr/search?keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5")

url <- html_nodes(html,'h2.headline')%>%
  html_nodes('a')%>%
  html_attr('href')

length(url)

#인코딩(encoding) ASCII문자(16진값)
인공지능 -> %EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5
#디코딩(decoding)
인공지능 <- %EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5

 

# html_attr : " " 안에 있는 문자 추출

 

2) 수집된 url을 이용해서 본문 뉴스 내용 수집

news <- c()
for(i in 1:length(url)){
  html <- read_html(url[i])
  temp <- html_nodes(html,'div.article_body.fs3')%>%
    html_text()
  news <- c(news,temp)
  Sys.sleep(2)
}

3) 수집한 기사(txt) 저장 및 불러오기

write(str_trim(news),'c:/data/news.txt') #수집한 기사 data 폴더에 저장
ai_news <- readLines('c:/data/news.txt') #불러오기

[문제206] 동아일보 '인공지능' 뉴스기사 검색을 통해 본문기사 내용을 donga_ai.txt로 저장하고, 본문 뉴스 기사 내용을 명사만 추출해서 wordcloud로 시각화 해주세요. 단 뉴스 기사는 5페이지까지 수집하세요.

 

https://www.donga.com/news/search?p=1&query=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&check_news=1&more=1&sorting=1&search_date=1&v1=&v2=&range=1: 1페이지
https://www.donga.com/news/search?p=16&query=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&check_news=1&more=1&sorting=1&search_date=1&v1=&v2=&range=1 : 2페이지
https://www.donga.com/news/search?p=31&query=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&check_news=1&more=1&sorting=1&search_date=1&v1=&v2=&range=1 : 3페이지
https://www.donga.com/news/search?p=46&query=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&check_news=1&more=1&sorting=1&search_date=1&v1=&v2=&range=1 : 4페이지
https://www.donga.com/news/search?p=61&query=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&check_news=1&more=1&sorting=1&search_date=1&v1=&v2=&range=1 : 5페이지

 

1) url 수집

library(rvest)
url <- c()
for(i in seq(1,61,by=15)){
  url_text <- paste0("https://www.donga.com/news/search?p=",i,
  "&query=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&check_news=1&more=1&sorting=1&search_date=1&v1=&v2=&range=1")
  html <- read_html(url_text)
  temp <- html_nodes(html,'p.tit')%>%
    html_node('a')%>% 
    html_attr('href')
  url <- c(url,temp)
  Sys.sleep(1)
}

2) url 활용 본문 기사 txt 추출 및 전처리

library(xml2) 
library(stringr)
news <- c()
for(i in 1:length(url)){
  html <- read_html(url[i])
  article <- html_nodes(html,'div.article_txt')
  xml2::xml_remove(article%>%html_nodes('div'))
  #xml2::xml_remove : 특정한 태그를 제거할때 사용하는 함수, 제거해서 바로 적용된다.
  text <- str_trim(article%>%html_text())
  text <- str_replace_all(text,'\\[서울=뉴시스\\]','')
  text <- str_replace_all(text,'[^\\.]+[A-z0-9._]+@[A-z0-9._]+','') 
  #[^\\.]+ : .이 아닌 1개 이상의 모든 문자열(. 뒤의 모든 문자열/공백)
  news <- c(news,text)
}

3) 텍스트 내 쓸모없는 부분 제거

news <- str_replace_all(news,'(\r|\n)','')

4) 저장 및 불러오기

write(news,'c:/data/donga_ai.txt')
ai <- readLines('c:/data/donga_ai.txt')

5) 데이터 마이닝

ai <- paste(ai,collapse = ' ')

library(KoNLP)
ai_pos <- SimplePos09(ai)
library(stringr)
word <- str_match(ai_pos,'([가-힣]+)/N')[,2]
#([가-힣]+)/N : [가-힣]+/N(1열) & [가-힣]+(2열) 둘 다

word <- word[nchar(word)>=2]
word_df <- data.frame(table(word))

6) 시각화

library(wordcloud2)
wordcloud2(word_df)

[문제207] 네이버 영화리뷰정보를 수집한 후 데이터 프레임으로 저장해주세요. 컬럼은 id, date, point, comment로 생성해주세요.

1) 안녕 자두야 제주도편 데이터 수집

https://movie.naver.com/movie/point/af/list.naver?st=mcode&sword=208821&target=after&page=1
https://movie.naver.com/movie/point/af/list.naver?st=mcode&sword=208821&target=after&page=13

library(stringr)
library(rvest)
library(xml2) 

df <- data.frame()
review <- data.frame()
for(i in 1:13){
  html <- rvest::read_html(paste0('https://movie.naver.com/movie/point/af/list.naver?st=mcode&sword=208821&target=after&page=',i))
  #닉네임 추출
  id <- html_nodes(html,'td.num>a')%>%
    html_text()
  #날짜추출
  x <- html_nodes(html,'td.num')%>%
    html_text()
  date <- unlist(str_extract_all(x,'\\d{2}\\.\\d{2}\\.\\d{2}'))
  #평점추출
  point <- html_nodes(html,"div.list_netizen_score>em")%>%
    html_text()
  #감상평 추출
  comment <- html_nodes(html,'td.title')
  xml_remove(comment%>%html_nodes('a'))
  xml_remove(comment%>%html_nodes('div'))
  comment <- comment%>%html_text(trim=T)
  
  df <- data.frame(id,date,point,comment)
  review <- rbind(review,df)
}

+) 만약 닉네임 + 날짜 추출시

unlist(str_extract_all(x,'\\w{1,}\\*{1,}\\d{2}\\.\\d{2}\\.\\d{2}'))

2) 단어 수출

library(KoNLP)
pos <- SimplePos22(review$comment)
review$tagging <- sapply(pos, function(x){paste(unlist(x),collapse = ' ')})

noun <- sapply(review$tagging,function(x){str_match_all(x,'([가-힣]+)/NC')})

review$noun <- sapply(noun,function(x){paste(unlist(x)[,2],collapse = ' ')})

3) 긍정단어/부정단어 구분하기

review$point <- as.integer(review$point)
review$evalution <- ifelse(review$point >=8,'긍정','부정')

positive <- review[review$evalution == '긍정','noun']
negative <- review[review$evalution == '부정','noun']

wordcloud2(data.frame(table(unlist(strsplit(positive,' ')))))
wordcloud2(data.frame(table(unlist(strsplit(negative,' ')))))

p <- data.frame(table(unlist(strsplit(positive,' '))))
n <- data.frame(table(unlist(strsplit(negative,' '))))

names(p) <- c('word','freq')
names(n) <- c('word','freq')

p$sentiment <- 'positive'
n$sentiment <- 'negative'

df<-rbind(p,n)

library(reshape2)
df_compar <- acast(df,word~sentiment,value.var = 'freq',fill=0)

7) 시각화

library(wordcloud)
windows(width=10,height=10) #새로운 창 열어서 시각화
wordcloud::comparison.cloud(df_compar,colors = c('red','blue'),
                            title.colors = c('red','blue'),
                            title.bg.colors = 'white',
                            title.size=2,
                            scale=c(2,0.5))

 

'R' 카테고리의 다른 글

[R] web scraping - selenium  (0) 2022.02.10
[R] web scraping - css, xpath,JSON  (0) 2022.02.10
[R] 텍스트 마이닝  (0) 2022.02.08
[R] 문제풀이  (0) 2022.02.07
[R] stringr  (0) 2022.02.04
Recent Posts
Popular Posts
Recent Comments