텍스트마이닝

텍스트마이닝 #5 실시간 뉴스 수집과 분석

yul_S2 2022. 12. 13. 11:36
반응형

# 1. 웹 문서 요청과 파싱 관련 패키지 설치 및 로딩

install.packages("httr")
library(httr)
install.packages("XML")
library(XML)

 

# 2. 웹 문서 요청

url <- "http://media.daum.net"
web <- GET(url)
web

 

 

# 3. HTML 파싱하기

html <- htmlTreeParse(web, useInternalNodes = T, trim = T, encoding = "utf-8")
rootNode <- xmlRoot(html)
  • htmlTreeParse
  • useInternalNodes = T : ROOT 노드 찾을 수 있음
  • trim = T : 앞뒤 공백제거
  • ncoding => 인코딩 방식 설정 
  • rootNode <- xmlRoot(html) : ROOT 노드 찾기

 

 

# 4. 태그 자료 수집하기

news <- xpathSApply(rootNode, "//a[@class = 'link_txt']", xmlValue)
news
  • root에 저장된 HTML 소스에서 해당 tag들중 조건( "//a[@class = 'link_txt']" )에 맞는 태그들의 Value, 내용을 뽑아서 벡터로 저장

 

 

 

# 5. 수집한 자료 전처리

# 5-1 자료 전처리 - 수집한 문서를 대상으로 불용어 제거

news_pre <- gsub("[\r\n\t]", ' ', news)
news_pre <- gsub('[[:punct:]]', ' ', news_pre)
news_pre <- gsub('[[:cntrl:]]', ' ', news_pre)
# news_pre <- gsub('\\d+', ' ', news_pre)                  # corona19(covid19) 때문에 숫자 제거 생략
news_pre <- gsub('[a-z]+', ' ', news_pre)
news_pre <- gsub('[A-Z]+', ' ', news_pre)
news_pre <- gsub('\\s+', ' ', news_pre)
news_pre
  • gsub("패턴", "교체문자", 원본
  • [[:punct:]] => 문장부호
  • [[:cntrl:]] => 특수문자
  • [원하는문장부호] 제거
  • \\d+ => 숫자
  • [a-z]+ / [A-Z]+ => 소 / 대문자 영어
  • \\s+ => 2개 이상 공백 교체

 

 

# 5-2 기사와 관계 없는 'TODAY', '검색어 순위' 등의 내용은 제거

news_data <- news_pre[1:32]
news_data

 

# 6 수집한 자료를 파일로 저장하고 읽기 

write.csv(news_data, "news_data.csv", quote = F)             # 파일저장 
news_data <- read.csv("news_data.csv", header = T, stringsAsFactors = F)       # 파일읽기
str(news_data)
'data.frame': 32 obs. of  2 variables:
  $ X: int  1 2 3 4 5 6 7 8 9 10 ...
# $ x: chr  " 단독 기재위 소위 협상 물꼬 트이나 與 민주당에 소위 신설 제안 "
# " 인사이드 스토리 ①삼성생명이 펫보험 팔게 된다면 " 
# " 수능 하루전이지만 유통 외식업계 마케팅 활동 잠잠 " " 갑갑한 지하철 버스 꺼려지면 이것 의심을 " ...

names(news_data) <- c("no", "news_text")
head(news_data)
# no                                                      news_text
# 1  1  단독 기재위 소위 협상 물꼬 트이나 與 민주당에 소위 신설 제안 
# 2  2               인사이드 스토리 ①삼성생명이 펫보험 팔게 된다면 
# 3  3              수능 하루전이지만 유통 외식업계 마케팅 활동 잠잠 
# 4  4                       갑갑한 지하철 버스 꺼려지면 이것 의심을 
# 5  5         수능 수험생 2317명 확진 판정 500명 내일 격리해제 종합 
# 6  6                     순방결산 한미일 중국 편 가르기 확실해졌다 

news_text <- news_data$news_text
news_text
# [1] " 단독 기재위 소위 협상 물꼬 트이나 與 민주당에 소위 신설 제안 "                     
# [2] " 인사이드 스토리 ①삼성생명이 펫보험 팔게 된다면 "                                  
# [3] " 수능 하루전이지만 유통 외식업계 마케팅 활동 잠잠 "                                 
# [4] " 갑갑한 지하철 버스 꺼려지면 이것 의심을 "                                          
# [5] " 수능 수험생 2317명 확진 판정 500명 내일 격리해제 종합 "                            
# [6] " 순방결산 한미일 중국 편 가르기 확실해졌다 "                                        
# [7] " 미 당국 폴란드 떨어진 미사일 우크라 발사 요격 미사일 추정 "                        
# [8] " 경찰이 통제해라 첫 112 신고 육성 들어보니 "                                        
# [9] " 검찰 급식 일감 몰아주기 최지성 삼성전자 기소 "                                     
# [10] " 현대해상 이어 손보도 신용대출 문턱 높인다 보험권 대출 한파 "                       
# [11] " 바이든 시진핑 이어 美재무 中인민은행 총재도 대면 회의 건설적 "                     
# [12] " 이재명 고금리 서민 고통 커 정부 역할 확대해 금융지원 강화 "                        
# [13] " 3년 만에 정상개최 지스타 안전 재미 동시에 잡는다 "                                 
# [14] " 집값 하락 경기 침체에 부산 부동산시장 얼어붙었다 "                                 
# [15] " 경기침체 충격 본격화 코스피 상장사 영업익 30 줄었다 "                              
# [16] " 김기현 빈곤 포르노 장경태 인간 아냐 동물을 어떻게 제소할까 "                       
# [17] " 트럼프 3번째 대선 출마 선언 공화당 입장에선 최악 타이밍 "                          
# [18] " 단독 정부 안전인력 감축 없다 더니 코레일 안전인력 784명 감축 검토 "                
# [19] " 日 다시 코로나 대유행하나 확진자 하루 10만 재돌파 "                                
# [20] " 민주당 제주도당 이태원 참사 국정조사 특검 서명운동 "                               
# [21] " 이앤피 서울시 지원 중단 내년 7월 2024년 여지 남았나 外 "                           
# [22] " 오마이포토 참사 현장 추모의 벽 에 비닐 붙은 이유 "                                 
# [23] " 영상 왜 내 차쪽으로 쓸어 미화원 무릎 꿇린 부부에 공분 차이나픽 "                   
# [24] " 자식 혁명 계승자로 키워야 北이 말하는 어머니 "                                     
# [25] " 친절한 경제 올해 김장 비용 걱정 안 해도 된다 배추 값 영향 "                        
# [26] " 월드리포트 헤르손 해방된 도시 환호하는 시민들 이면의 상처 "                        
# [27] " 소설 위대한 알코올중독자 모든 길은 술로 통한다 "                                   
# [28] " 이슈 직설 99 의 투자자는 안 낼까 금투세 에 뿔난 개미들 금투세 과세 대상자 15만 명 "
# [29] "줄지어서 주의사항 듣는 수험생들"                                                    
# [30] " 향숙이 예뻤다 화성 연쇄살인범 이춘재 대신 누명 윤성여 에 국가 19억 배상"           
# [31] " 참사 현장 추모의 벽 에 비닐 붙은 이유"                                             
# [32] "美 바이든 폴란드 미사일 피격에 7 나토 정상들과 긴급 회동 "

 

# 7.토픽분석 

# 7-1 세종 사전에 단어 추가

user_dic <- data.frame(term = c("펜데믹", "코로나19", "타다"), tag = 'ncn')
buildDictionary(ext_dic = 'sejong', user_dic = user_dic)
# 371005 words dictionary was built.

 

 

# 7-2 단어 추출 사용자 함수 정의하기 ( 토픽분석 )

#(1) 사용자 정의 함수 작성

exNouns <- function(x) { paste(extractNoun(x), collapse = " ")}

 

#(2) exNouns() 함수를 이용하어 단어 추출

news_nouns <- sapply(news_text, exNouns)
news_nouns

 

#(3) 추출 결과 확인

str(news_nouns)
# Named chr [1:32] "단독 기재 위 협상 물꼬 與 민주 당 신설 저" "인사이드 스토리 1삼성생명이 펫보험 면" ...
# - attr(*, "names")= chr [1:32] " 단독 기재위 소위 협상 물꼬 트이나 與 민주당에 소위 신설 제안 "
# " 인사이드 스토리 ①삼성생명이 펫보험 팔게 된다면 " " 수능 하루전이지만 유통 외식업계 마케팅 활동 잠잠 " 
# " 갑갑한 지하철 버스 꺼려지면 이것 의심을 " ...

 

 

 

# 7-3 말뭉치 생성과 집계 행렬 만들기

library(tm)

#(1) 추출된 단어를 이용한 말뭉치(corpus) 생성

newsCorpus <- Corpus(VectorSource(news_nouns))

newsCorpus
# <<SimpleCorpus>>
# Metadata:  corpus specific: 1, document level (indexed): 0
# Content:  documents: 32

inspect(newsCorpus[1:5]) 

 

 

#(2) 단어 vs 문서 집계 행렬 만들기

TDM <- TermDocumentMatrix(newsCorpus, control = list(wordLengths = c(4, 16)))
TDM
# <<TermDocumentMatrix (terms: 175, documents: 32)>>
# Non-/sparse entries: 190/5410
# Sparsity           : 97%
# Maximal term length: 6
# Weighting          : term frequency (tf)

 

 

#(3) matrix 자료구조를 data.frame 자료구조로 변경

tdm.df <- as.data.frame(as.matrix(TDM))
dim(tdm.df)
# [1] 175  32

 

 

#7-4 단어 출현 빈도수 구하기

wordResult <- sort(rowSums(tdm.df), decreasing = TRUE)
wordResult[1:10]
# 미사일   안전   참사   단독   민주   수능   하루 수험생 폴란드   정부 
# 3      3      3      2      2      2      2      2      2      2 

 

 

#7-5 단어 구름 생성

#(1) 패키지 로딩과 단어 이름 추출

library(wordcloud)

myNames <- names(wordResult)
myNames

 

 

 

# (2)  단어와 단어 빈도수 구하기

df <- data.frame(word = myNames, freq = wordResult)
head(df)
#                word freq
# 미사일 미사일    3
# 안전     안전    3
# 참사     참사    3
# 단독     단독    2
# 민주     민주    2
# 수능     수능    2

 

 

# (3)  단어 구름 생성

pal <- brewer.pal(12, "Paired")                             ###  pas 대신--> pal
wordcloud(df$word, df$freq, min.freq = 2,
          random.order = F, scale = c(4, 0.7),
          rot.per = .1, colors = pal, family = "malgun") 

 

반응형