Web scraping in practice

library(XML)
library(rvest)
## Loading required package: xml2
## 
## Attaching package: 'rvest'
## The following object is masked from 'package:XML':
## 
##     xml
library(stringr)
page <- readLines("https://news.daum.net/ranking/popular")
page_parsed <- htmlParse(page)

First Headline XPath: ‘//[@id="mArticle"]/div[2]/ul[3]/li[1]/div[2]/strong/a’ Second Headline XPath: ’//[@id="mArticle"]/div[2]/ul[3]/li[2]/div[2]/strong/a’

First Company XPath: ‘//[@id="mArticle"]/div[2]/ul[3]/li[1]/div[2]/strong/span’ Second Company XPath: ’//[@id="mArticle"]/div[2]/ul[3]/li[2]/div[2]/strong/span’

headline_xpath <- '//*[@id="mArticle"]/div[2]/ul[3]/li/div[2]/strong/a'
company_xpath <- '//*[@id="mArticle"]/div[2]/ul[3]/li/div[2]/strong/span'

headlines <- xpathSApply(page_parsed, headline_xpath, xmlValue)
headlines
##  [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                                   
##  [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                                     
##  [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""              
##  [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                              
##  [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"                                      
##  [6] "[단독] \"경비원에게 이런 일을, 너무 잔인\" 대학생의 일갈"                             
##  [7] "화이자 CEO, '백신 효과' 발표 당일 \"62억원어치 주식 매각\""                           
##  [8] "제트기 동원해 독일로 환자 이송..\"의료붕괴 위기\""                                    
##  [9] "트럼프를 아는 이들은 말린다..전 부인 \"골프 치며 살길\""                              
## [10] "\"아이폰12 너무 비싸 ㅠㅠ\" 90만원→3만원 '똥값'된 아이폰XR 구매 문의 급증! [IT선빵!]"
## [11] "'입주하려는데 현관문에 용접이..' 울산 대명루첸 또 '시끌'"                             
## [12] "전동킥보드 규제 풀어준 의원들..뒤늦게 \"안 타봐서\""                                  
## [13] "추미애 \"보수·진보언론 안 가리고 윤석열 띄워..국민 우려\"(종합)"                     
## [14] "[단독] '학대 동영상' 또 있었다..'두 얼굴의 엄마' 구속"                                
## [15] "윤석열 부인 회사 과세자료 확보..\"무리한 수사\" vs \"원칙대로\""                      
## [16] "김봉현 \"검사 술접대 증거, 차량 내비게이션에 남았을 것\""                             
## [17] "어제 끼고 오늘 또 끼고..마스크 재사용 괜찮을까?"                                      
## [18] "\"확산세 계속되면 거리두기 격상\"..1.5단계 뭐가 달라지나?"                            
## [19] "최재형 \"월성원전, 범죄 개연성 있어 檢에 참고자료 보내\"(종합)"                       
## [20] "[현장영상] 서울 하늘에 처음 뜬 '드론택시'..누가 탔나? 요금은?"                        
## [21] "김봉현\"룸살롱 접대 작년 7월12일..검사 집까지 차로, 내비에 증거\"(종합)"              
## [22] "日 전역서 '하루 최다' 속출..\"코로나19 3차 유행 왔다\""                               
## [23] "'전설의 대물' 돗돔, 3년 만에 경매에..통영서 양식 도전"                                
## [24] "수천만원 주고 정교사된 사학 기간제교사들 무더기 송치(종합)"                           
## [25] "[단독]\"위험하다고 말렸는데..\" 음주운전 차량에 23살 배달원 다리 절단"                
## [26] "\"일단 도수치료 하시죠\" 제동?..의사 책임 묻는다"                                     
## [27] "백신 나오면 마스크 없는 일상으로?..\"시간 더 필요\""                                  
## [28] "12조 원 규모 철도 건설 추진..현실성은?"                                               
## [29] "'화이자 백신' 日 1억 회분 '선주문' 했는데..한국 \"협상 중\""                          
## [30] "26년 전 쫓겨난 서의현, 또다시 조계종을 뒤흔들다"                                      
## [31] "네 살 아이 두 눈에 시퍼런 피멍 들 때까지 때린 40대"                                   
## [32] "김해 신공항 백지화 가닥..선거용 변질, 지역 갈등 '뇌관'으로"                           
## [33] "\"보건소서 괜찮다했는데..독감주사 맞은 누이, 이틀뒤 사망\""                           
## [34] "교사들 \"코로나19 장기화, 대면수업 늘려야 .. 교육부 예산은 '원격수업' 치중\""         
## [35] "잘못된 수요예측, 비싼 통행료 받고도 혈세 1조6667억 '꿀꺽'"                            
## [36] "하루평균 확진자 100명 육박..정부 \"2~3주 내 1.5단계 가능성\""                         
## [37] "[오늘 이 뉴스] \"여전히 고통..\" 고유정 사건 또 다른 피해자"                          
## [38] "'630억 재산피해' 군포물류센터 실화 혐의 튀니지인 무죄 선고(종합)"                     
## [39] "[사건의 재구성] \"내 여친에 연락 그만해\" 죽기 직전까지 얻어맞은 옛 남친"             
## [40] "[집중취재M] 기자가 '택배'로만 1주일 살아봤습니다"                                     
## [41] "바이든 사람들은 읽씹 중인데..방미 강경화의 '난센스 외교'"                             
## [42] "동료 의원에 축의금 100만원 건넨 道 의장· 부의장 검찰 송치"                           
## [43] "'술집부터 미행 음주차에 고의 사고' 돈 뜯어낸 20대"                                    
## [44] "[밀착카메라] 쓰레기 쌓이는 '캠핑 명소'..실종된 에티켓"                                
## [45] "이재명 \"연애는 필수, 결혼은 선택?.. 더 이상, 결혼·출산 포기 되어선 안돼\""          
## [46] "美대선불복 와중에 강경화, 트럼프·바이든 양쪽에 손 내밀었다"                          
## [47] "[팩트체크] 영하 70도 백신 유통, 국내에서는 불가능하다?"                               
## [48] "국민의힘, 잡기엔 뜨거운 감자들 '윤·안·금'을 어쩌나"                                 
## [49] "\"담임카톡 못 받아 우는데, 결국 폰 샀죠\" 학부모들 한숨"                              
## [50] "혼전계약서 쓴 트럼프, 멜라니아 이혼땐 14살 아들도 뺏긴다?"
companies <- xpathSApply(page_parsed, company_xpath, xmlValue)
companies
##  [1] "JTBC"       "SBS"        "뉴스1"      "뉴스1"      "MBC"       
##  [6] "오마이뉴스" "연합뉴스"   "MBC"        "JTBC"       "헤럴드경제"
## [11] "연합뉴스"   "JTBC"       "뉴시스"     "MBC"        "KBS"       
## [16] "연합뉴스"   "머니투데이" "KBS"        "연합뉴스"   "KBS"       
## [21] "뉴스1"      "KBS"        "JTBC"       "연합뉴스"   "동아일보"  
## [26] "MBC"        "JTBC"       "KBS"        "채널A"      "한국일보"  
## [31] "연합뉴스"   "경향신문"   "중앙일보"   "서울신문"   "경향신문"  
## [36] "KBS"        "MBC"        "연합뉴스"   "뉴스1"      "MBC"       
## [41] "중앙일보"   "뉴시스"     "뉴시스"     "JTBC"       "머니S"     
## [46] "중앙일보"   "JTBC"       "경향신문"   "국민일보"   "중앙일보"

Five steps of web scraping

  1. We identify the running mechanism in the URL syntax.
  2. We retrieve links to the running pages.
  3. We download the running pages.
  4. We retrieve links to the entries on the running pages.
  5. We download the single entries.

Manipulating URLs to access multiple pages

baseurl <- "https://news.daum.net/ranking/popular?regDate="
dates <- seq(from=20201025, to=20201031, by=1)
urls <- str_c(baseurl, dates)
urls
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
## [2] "https://news.daum.net/ranking/popular?regDate=20201026"
## [3] "https://news.daum.net/ranking/popular?regDate=20201027"
## [4] "https://news.daum.net/ranking/popular?regDate=20201028"
## [5] "https://news.daum.net/ranking/popular?regDate=20201029"
## [6] "https://news.daum.net/ranking/popular?regDate=20201030"
## [7] "https://news.daum.net/ranking/popular?regDate=20201031"

What is a function? What is the function, lapply()?

Function

Function

urls
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
## [2] "https://news.daum.net/ranking/popular?regDate=20201026"
## [3] "https://news.daum.net/ranking/popular?regDate=20201027"
## [4] "https://news.daum.net/ranking/popular?regDate=20201028"
## [5] "https://news.daum.net/ranking/popular?regDate=20201029"
## [6] "https://news.daum.net/ranking/popular?regDate=20201030"
## [7] "https://news.daum.net/ranking/popular?regDate=20201031"
remove_numbers <- function(x){
  library(stringr)
  y <- str_remove(x, "[[:digit:]]+")
  return(y)
}

?lapply
## starting httpd help server ... done
class(lapply(urls, remove_numbers))
## [1] "list"
lapply(urls, remove_numbers)
## [[1]]
## [1] "https://news.daum.net/ranking/popular?regDate="
## 
## [[2]]
## [1] "https://news.daum.net/ranking/popular?regDate="
## 
## [[3]]
## [1] "https://news.daum.net/ranking/popular?regDate="
## 
## [[4]]
## [1] "https://news.daum.net/ranking/popular?regDate="
## 
## [[5]]
## [1] "https://news.daum.net/ranking/popular?regDate="
## 
## [[6]]
## [1] "https://news.daum.net/ranking/popular?regDate="
## 
## [[7]]
## [1] "https://news.daum.net/ranking/popular?regDate="

R Basics for Web Scraping

Creating vectors

A sequence of numbers/integers, characters, or Booleans

c(1,3,5) # Join elements into a vector 
## [1] 1 3 5
1:5 # An integer sequence
## [1] 1 2 3 4 5
seq(1, 5, by=2) # A sequence of integers from 1 to 5, increasing by 2
## [1] 1 3 5
rep(1:5, times=3) # Repeat an integer sequence 1:5 three times
##  [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
rep(1:5, each=3) # Repeat each element of an integer sequence 1:5 three times
##  [1] 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5

Vector functions

# R is an object-oriented programming language; everything can be assigned to an object
headlines
##  [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                                   
##  [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                                     
##  [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""              
##  [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                              
##  [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"                                      
##  [6] "[단독] \"경비원에게 이런 일을, 너무 잔인\" 대학생의 일갈"                             
##  [7] "화이자 CEO, '백신 효과' 발표 당일 \"62억원어치 주식 매각\""                           
##  [8] "제트기 동원해 독일로 환자 이송..\"의료붕괴 위기\""                                    
##  [9] "트럼프를 아는 이들은 말린다..전 부인 \"골프 치며 살길\""                              
## [10] "\"아이폰12 너무 비싸 ㅠㅠ\" 90만원→3만원 '똥값'된 아이폰XR 구매 문의 급증! [IT선빵!]"
## [11] "'입주하려는데 현관문에 용접이..' 울산 대명루첸 또 '시끌'"                             
## [12] "전동킥보드 규제 풀어준 의원들..뒤늦게 \"안 타봐서\""                                  
## [13] "추미애 \"보수·진보언론 안 가리고 윤석열 띄워..국민 우려\"(종합)"                     
## [14] "[단독] '학대 동영상' 또 있었다..'두 얼굴의 엄마' 구속"                                
## [15] "윤석열 부인 회사 과세자료 확보..\"무리한 수사\" vs \"원칙대로\""                      
## [16] "김봉현 \"검사 술접대 증거, 차량 내비게이션에 남았을 것\""                             
## [17] "어제 끼고 오늘 또 끼고..마스크 재사용 괜찮을까?"                                      
## [18] "\"확산세 계속되면 거리두기 격상\"..1.5단계 뭐가 달라지나?"                            
## [19] "최재형 \"월성원전, 범죄 개연성 있어 檢에 참고자료 보내\"(종합)"                       
## [20] "[현장영상] 서울 하늘에 처음 뜬 '드론택시'..누가 탔나? 요금은?"                        
## [21] "김봉현\"룸살롱 접대 작년 7월12일..검사 집까지 차로, 내비에 증거\"(종합)"              
## [22] "日 전역서 '하루 최다' 속출..\"코로나19 3차 유행 왔다\""                               
## [23] "'전설의 대물' 돗돔, 3년 만에 경매에..통영서 양식 도전"                                
## [24] "수천만원 주고 정교사된 사학 기간제교사들 무더기 송치(종합)"                           
## [25] "[단독]\"위험하다고 말렸는데..\" 음주운전 차량에 23살 배달원 다리 절단"                
## [26] "\"일단 도수치료 하시죠\" 제동?..의사 책임 묻는다"                                     
## [27] "백신 나오면 마스크 없는 일상으로?..\"시간 더 필요\""                                  
## [28] "12조 원 규모 철도 건설 추진..현실성은?"                                               
## [29] "'화이자 백신' 日 1억 회분 '선주문' 했는데..한국 \"협상 중\""                          
## [30] "26년 전 쫓겨난 서의현, 또다시 조계종을 뒤흔들다"                                      
## [31] "네 살 아이 두 눈에 시퍼런 피멍 들 때까지 때린 40대"                                   
## [32] "김해 신공항 백지화 가닥..선거용 변질, 지역 갈등 '뇌관'으로"                           
## [33] "\"보건소서 괜찮다했는데..독감주사 맞은 누이, 이틀뒤 사망\""                           
## [34] "교사들 \"코로나19 장기화, 대면수업 늘려야 .. 교육부 예산은 '원격수업' 치중\""         
## [35] "잘못된 수요예측, 비싼 통행료 받고도 혈세 1조6667억 '꿀꺽'"                            
## [36] "하루평균 확진자 100명 육박..정부 \"2~3주 내 1.5단계 가능성\""                         
## [37] "[오늘 이 뉴스] \"여전히 고통..\" 고유정 사건 또 다른 피해자"                          
## [38] "'630억 재산피해' 군포물류센터 실화 혐의 튀니지인 무죄 선고(종합)"                     
## [39] "[사건의 재구성] \"내 여친에 연락 그만해\" 죽기 직전까지 얻어맞은 옛 남친"             
## [40] "[집중취재M] 기자가 '택배'로만 1주일 살아봤습니다"                                     
## [41] "바이든 사람들은 읽씹 중인데..방미 강경화의 '난센스 외교'"                             
## [42] "동료 의원에 축의금 100만원 건넨 道 의장· 부의장 검찰 송치"                           
## [43] "'술집부터 미행 음주차에 고의 사고' 돈 뜯어낸 20대"                                    
## [44] "[밀착카메라] 쓰레기 쌓이는 '캠핑 명소'..실종된 에티켓"                                
## [45] "이재명 \"연애는 필수, 결혼은 선택?.. 더 이상, 결혼·출산 포기 되어선 안돼\""          
## [46] "美대선불복 와중에 강경화, 트럼프·바이든 양쪽에 손 내밀었다"                          
## [47] "[팩트체크] 영하 70도 백신 유통, 국내에서는 불가능하다?"                               
## [48] "국민의힘, 잡기엔 뜨거운 감자들 '윤·안·금'을 어쩌나"                                 
## [49] "\"담임카톡 못 받아 우는데, 결국 폰 샀죠\" 학부모들 한숨"                              
## [50] "혼전계약서 쓴 트럼프, 멜라니아 이혼땐 14살 아들도 뺏긴다?"
h_vector <- headlines[1:5]
h_vector
## [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                     
## [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                       
## [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""
## [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                
## [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"
companies
##  [1] "JTBC"       "SBS"        "뉴스1"      "뉴스1"      "MBC"       
##  [6] "오마이뉴스" "연합뉴스"   "MBC"        "JTBC"       "헤럴드경제"
## [11] "연합뉴스"   "JTBC"       "뉴시스"     "MBC"        "KBS"       
## [16] "연합뉴스"   "머니투데이" "KBS"        "연합뉴스"   "KBS"       
## [21] "뉴스1"      "KBS"        "JTBC"       "연합뉴스"   "동아일보"  
## [26] "MBC"        "JTBC"       "KBS"        "채널A"      "한국일보"  
## [31] "연합뉴스"   "경향신문"   "중앙일보"   "서울신문"   "경향신문"  
## [36] "KBS"        "MBC"        "연합뉴스"   "뉴스1"      "MBC"       
## [41] "중앙일보"   "뉴시스"     "뉴시스"     "JTBC"       "머니S"     
## [46] "중앙일보"   "JTBC"       "경향신문"   "국민일보"   "중앙일보"
c_vector <- companies[1:5]
c_vector
## [1] "JTBC"  "SBS"   "뉴스1" "뉴스1" "MBC"
dates
## [1] 20201025 20201026 20201027 20201028 20201029 20201030 20201031
d_vector <- c(rep(dates[1],3),rep(dates[2],2))
d_vector
## [1] 20201025 20201025 20201025 20201026 20201026

list( )

What is a vector object? A collection of ordered elements in the same nature.

Ex) a vector of headlines; a vector of company names; a vector of dates …

What is a list object?

A vector with possible heterogeneous elements. That is, a list is collection of elements which can be of different contents or types.

The elements of a list can include character vectors and numeric vectors at once.

Let say we want to generate a list object that contains the above three vector objects all together.

We can use a function list( ) here.

List1 <- list(headline=h_vector, company=c_vector, date=d_vector) # Generate a list object, List1, to contain all the elements that are named "headline", "company", and "date"
List1
## $headline
## [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                     
## [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                       
## [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""
## [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                
## [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"                        
## 
## $company
## [1] "JTBC"  "SBS"   "뉴스1" "뉴스1" "MBC"  
## 
## $date
## [1] 20201025 20201025 20201025 20201026 20201026
length(List1) # The function, length, calculates how many elements are in any R object (vectors, lists, & factors).
## [1] 3
class(List1) # R is an object-oriented style of programming. The function, class, allows us to know what type an object belongs to. It can be numeric, character, logical, list, and so on...
## [1] "list"
names(List1) # To get or set the names of an object; Here, elements' names are "headline", "company", and "date"
## [1] "headline" "company"  "date"
List1[1:2] # returns a new list object that contains the first and the second elements. What is length(List1[1:2])?
## $headline
## [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                     
## [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                       
## [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""
## [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                
## [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"                        
## 
## $company
## [1] "JTBC"  "SBS"   "뉴스1" "뉴스1" "MBC"
List1[2] # returns a new list object that contains the second element only. What is length(List1[2])?
## $company
## [1] "JTBC"  "SBS"   "뉴스1" "뉴스1" "MBC"
length(List1[2])
## [1] 1
List1[[2]] # returns a vector object that contains five elements of company names in the second element of List1. What is length(List1[[2]])? 
## [1] "JTBC"  "SBS"   "뉴스1" "뉴스1" "MBC"
length(List1[[2]])
## [1] 5
List1['headline'] # returns a new list with the element named 'headline' only
## $headline
## [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                     
## [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                       
## [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""
## [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                
## [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"
List1[['headline']] # returns a vector with the elements of the list element named 'headline'
## [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                     
## [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                       
## [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""
## [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                
## [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"

Why is list( ) important in web scraping?

Web data are structured at multiple levels. The list( ) function is useful for dealing with hierarchical data.

Ex) DAUM News > Ranking News > Popular News > Top 50 List on Oct/25, Top 50 List on Oct/26, Top 50 List on Oct/27 …

Let say we have a list of ten URLs for popular news at DAUM on different dates

# Example
urls
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
## [2] "https://news.daum.net/ranking/popular?regDate=20201026"
## [3] "https://news.daum.net/ranking/popular?regDate=20201027"
## [4] "https://news.daum.net/ranking/popular?regDate=20201028"
## [5] "https://news.daum.net/ranking/popular?regDate=20201029"
## [6] "https://news.daum.net/ranking/popular?regDate=20201030"
## [7] "https://news.daum.net/ranking/popular?regDate=20201031"
class(urls)
## [1] "character"
urls[1]
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
urls_list <- as.list(urls)
urls_list
## [[1]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
## 
## [[2]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201026"
## 
## [[3]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201027"
## 
## [[4]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201028"
## 
## [[5]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201029"
## 
## [[6]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201030"
## 
## [[7]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201031"
class(urls_list)
## [1] "list"
urls_list[[1]] # URL for popular news at DAUM on 10/25
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
urls_list[[2]] # URL for popular news at DAUM on 10/26
## [1] "https://news.daum.net/ranking/popular?regDate=20201026"

How to turn a list into a vector

#unlist( ) is a function to turn a list object into a vector object
#be cautious about using the unlist function
class(urls_list)
## [1] "list"
unlist(urls_list) # turn a list object into a vector object
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
## [2] "https://news.daum.net/ranking/popular?regDate=20201026"
## [3] "https://news.daum.net/ranking/popular?regDate=20201027"
## [4] "https://news.daum.net/ranking/popular?regDate=20201028"
## [5] "https://news.daum.net/ranking/popular?regDate=20201029"
## [6] "https://news.daum.net/ranking/popular?regDate=20201030"
## [7] "https://news.daum.net/ranking/popular?regDate=20201031"
class(unlist(urls_list))
## [1] "character"
urls_list[[2]]
## [1] "https://news.daum.net/ranking/popular?regDate=20201026"
unlist(urls_list)
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
## [2] "https://news.daum.net/ranking/popular?regDate=20201026"
## [3] "https://news.daum.net/ranking/popular?regDate=20201027"
## [4] "https://news.daum.net/ranking/popular?regDate=20201028"
## [5] "https://news.daum.net/ranking/popular?regDate=20201029"
## [6] "https://news.daum.net/ranking/popular?regDate=20201030"
## [7] "https://news.daum.net/ranking/popular?regDate=20201031"

unlist( ) allows us to combine a list object’s elements into a vector object

The apply() Family

apply() and its derivative functions allow crossing the data in a number of ways and avoid explicit use of loop constructs. They act on an input list, matrix or array and apply a named function with one or several optional arguments.

lapply( ): Applies a function to a list and returns a list object

lapply( ) applies a specified function to each element of a list and returns a new list object of the same length as the input list object. Each element of which is the result of applying a function to the corresponding element of the input list.

l in lapply( ) stands for list

List2 <- list(1:3,4:6,7:9)
List2
## [[1]]
## [1] 1 2 3
## 
## [[2]]
## [1] 4 5 6
## 
## [[3]]
## [1] 7 8 9
class(List2)
## [1] "list"
add_two <- function(x){
  y <- x + 2
  return(y)
}

lapply(List2, add_two) # returns a list object of results from applying a function "add_two" to each element of List2 
## [[1]]
## [1] 3 4 5
## 
## [[2]]
## [1] 6 7 8
## 
## [[3]]
## [1]  9 10 11
lapply(List2, sum) # Built-in function
## [[1]]
## [1] 6
## 
## [[2]]
## [1] 15
## 
## [[3]]
## [1] 24
List2
## [[1]]
## [1] 1 2 3
## 
## [[2]]
## [1] 4 5 6
## 
## [[3]]
## [1] 7 8 9
class(List2)
## [1] "list"
unlist(List2)
## [1] 1 2 3 4 5 6 7 8 9
int_vec <- unlist(List2)
int_vec
## [1] 1 2 3 4 5 6 7 8 9
class(int_vec)
## [1] "integer"
as.list(int_vec)
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2
## 
## [[3]]
## [1] 3
## 
## [[4]]
## [1] 4
## 
## [[5]]
## [1] 5
## 
## [[6]]
## [1] 6
## 
## [[7]]
## [1] 7
## 
## [[8]]
## [1] 8
## 
## [[9]]
## [1] 9
lapply(int_vec, add_two)
## [[1]]
## [1] 3
## 
## [[2]]
## [1] 4
## 
## [[3]]
## [1] 5
## 
## [[4]]
## [1] 6
## 
## [[5]]
## [1] 7
## 
## [[6]]
## [1] 8
## 
## [[7]]
## [1] 9
## 
## [[8]]
## [1] 10
## 
## [[9]]
## [1] 11
lapply(as.list(int_vec), add_two)
## [[1]]
## [1] 3
## 
## [[2]]
## [1] 4
## 
## [[3]]
## [1] 5
## 
## [[4]]
## [1] 6
## 
## [[5]]
## [1] 7
## 
## [[6]]
## [1] 8
## 
## [[7]]
## [1] 9
## 
## [[8]]
## [1] 10
## 
## [[9]]
## [1] 11

sapply( ): Applies a function to a list and returns a vector (or matrix) object

sapply( ) applies a specified function to each element of a list and returns a vector object when possible. It is the same as applying the function unlist( ) to the result of lapply( ).

List2
## [[1]]
## [1] 1 2 3
## 
## [[2]]
## [1] 4 5 6
## 
## [[3]]
## [1] 7 8 9
lapply(List2, add_two)
## [[1]]
## [1] 3 4 5
## 
## [[2]]
## [1] 6 7 8
## 
## [[3]]
## [1]  9 10 11
sapply(List2, add_two) # applies a function "add_two" to elements as vectors in List2 as a list
##      [,1] [,2] [,3]
## [1,]    3    6    9
## [2,]    4    7   10
## [3,]    5    8   11
lapply(int_vec, add_two)
## [[1]]
## [1] 3
## 
## [[2]]
## [1] 4
## 
## [[3]]
## [1] 5
## 
## [[4]]
## [1] 6
## 
## [[5]]
## [1] 7
## 
## [[6]]
## [1] 8
## 
## [[7]]
## [1] 9
## 
## [[8]]
## [1] 10
## 
## [[9]]
## [1] 11
sapply(int_vec, add_two)
## [1]  3  4  5  6  7  8  9 10 11

sapply( ) is also applicable to elements in different formats.

library(stringr)
List1
## $headline
## [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                     
## [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                       
## [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""
## [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                
## [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"                        
## 
## $company
## [1] "JTBC"  "SBS"   "뉴스1" "뉴스1" "MBC"  
## 
## $date
## [1] 20201025 20201025 20201025 20201026 20201026
sapply(List1, str_length)
##      headline company date
## [1,]       32       4    8
## [2,]       28       3    8
## [3,]       42       3    8
## [4,]       33       3    8
## [5,]       28       3    8

tapply( ): Useful in applying to table

tapply( ) is used for applying a specified function to each element of a vector, grouped by another vector.

library(tidyverse)
## -- Attaching packages ---------------------------------- tidyverse 1.3.0 --
## √ ggplot2 3.3.0     √ purrr   0.3.4
## √ tibble  3.0.0     √ dplyr   1.0.1
## √ tidyr   1.0.2     √ forcats 0.5.0
## √ readr   1.3.1
## -- Conflicts ------------------------------------- tidyverse_conflicts() --
## x dplyr::filter()         masks stats::filter()
## x readr::guess_encoding() masks rvest::guess_encoding()
## x dplyr::lag()            masks stats::lag()
## x purrr::pluck()          masks rvest::pluck()
## x rvest::xml()            masks XML::xml()
mytable <- tibble(headline=h_vector, company=c_vector, date=d_vector) # Create a tibble object (data frame) with three variables
mytable # returns a table with the three vectors
## # A tibble: 5 x 3
##   headline                                                       company    date
##   <chr>                                                          <chr>     <dbl>
## 1 "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"           JTBC     2.02e7
## 2 "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"             SBS      2.02e7
## 3 "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""~ 뉴스1    2.02e7
## 4 "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"      뉴스1    2.02e7
## 5 "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"              MBC      2.02e7
mytable$headline # $ sign selects a column of a data frame named "headline"
## [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                     
## [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                       
## [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""
## [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                
## [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"
mytable$company
## [1] "JTBC"  "SBS"   "뉴스1" "뉴스1" "MBC"
mytable$date
## [1] 20201025 20201025 20201025 20201026 20201026

Say we want to count how many characters appear in headlines on 20201025 and in headlines on 20201026. Here each headline can be grouped by the variable date.

tapply(mytable$headline, mytable$date, str_length) # applies the function str_length to mytable$headline, grouped by mytable$date, and returns the result: the number of characters in each headline
## $`20201025`
## [1] 32 28 42
## 
## $`20201026`
## [1] 33 28

tapply(x,y,str_length): Applies the function str_length() to x as a vector of character length in each headline, grouped by y as another vector of dates.

Let’s practice on tapply( )

Let’s calculate how many headlines are in each company and how many characters are in the headlines, using the function tapply( ).

headlines
##  [1] "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                                   
##  [2] "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                                     
##  [3] "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""              
##  [4] "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"                              
##  [5] "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"                                      
##  [6] "[단독] \"경비원에게 이런 일을, 너무 잔인\" 대학생의 일갈"                             
##  [7] "화이자 CEO, '백신 효과' 발표 당일 \"62억원어치 주식 매각\""                           
##  [8] "제트기 동원해 독일로 환자 이송..\"의료붕괴 위기\""                                    
##  [9] "트럼프를 아는 이들은 말린다..전 부인 \"골프 치며 살길\""                              
## [10] "\"아이폰12 너무 비싸 ㅠㅠ\" 90만원→3만원 '똥값'된 아이폰XR 구매 문의 급증! [IT선빵!]"
## [11] "'입주하려는데 현관문에 용접이..' 울산 대명루첸 또 '시끌'"                             
## [12] "전동킥보드 규제 풀어준 의원들..뒤늦게 \"안 타봐서\""                                  
## [13] "추미애 \"보수·진보언론 안 가리고 윤석열 띄워..국민 우려\"(종합)"                     
## [14] "[단독] '학대 동영상' 또 있었다..'두 얼굴의 엄마' 구속"                                
## [15] "윤석열 부인 회사 과세자료 확보..\"무리한 수사\" vs \"원칙대로\""                      
## [16] "김봉현 \"검사 술접대 증거, 차량 내비게이션에 남았을 것\""                             
## [17] "어제 끼고 오늘 또 끼고..마스크 재사용 괜찮을까?"                                      
## [18] "\"확산세 계속되면 거리두기 격상\"..1.5단계 뭐가 달라지나?"                            
## [19] "최재형 \"월성원전, 범죄 개연성 있어 檢에 참고자료 보내\"(종합)"                       
## [20] "[현장영상] 서울 하늘에 처음 뜬 '드론택시'..누가 탔나? 요금은?"                        
## [21] "김봉현\"룸살롱 접대 작년 7월12일..검사 집까지 차로, 내비에 증거\"(종합)"              
## [22] "日 전역서 '하루 최다' 속출..\"코로나19 3차 유행 왔다\""                               
## [23] "'전설의 대물' 돗돔, 3년 만에 경매에..통영서 양식 도전"                                
## [24] "수천만원 주고 정교사된 사학 기간제교사들 무더기 송치(종합)"                           
## [25] "[단독]\"위험하다고 말렸는데..\" 음주운전 차량에 23살 배달원 다리 절단"                
## [26] "\"일단 도수치료 하시죠\" 제동?..의사 책임 묻는다"                                     
## [27] "백신 나오면 마스크 없는 일상으로?..\"시간 더 필요\""                                  
## [28] "12조 원 규모 철도 건설 추진..현실성은?"                                               
## [29] "'화이자 백신' 日 1억 회분 '선주문' 했는데..한국 \"협상 중\""                          
## [30] "26년 전 쫓겨난 서의현, 또다시 조계종을 뒤흔들다"                                      
## [31] "네 살 아이 두 눈에 시퍼런 피멍 들 때까지 때린 40대"                                   
## [32] "김해 신공항 백지화 가닥..선거용 변질, 지역 갈등 '뇌관'으로"                           
## [33] "\"보건소서 괜찮다했는데..독감주사 맞은 누이, 이틀뒤 사망\""                           
## [34] "교사들 \"코로나19 장기화, 대면수업 늘려야 .. 교육부 예산은 '원격수업' 치중\""         
## [35] "잘못된 수요예측, 비싼 통행료 받고도 혈세 1조6667억 '꿀꺽'"                            
## [36] "하루평균 확진자 100명 육박..정부 \"2~3주 내 1.5단계 가능성\""                         
## [37] "[오늘 이 뉴스] \"여전히 고통..\" 고유정 사건 또 다른 피해자"                          
## [38] "'630억 재산피해' 군포물류센터 실화 혐의 튀니지인 무죄 선고(종합)"                     
## [39] "[사건의 재구성] \"내 여친에 연락 그만해\" 죽기 직전까지 얻어맞은 옛 남친"             
## [40] "[집중취재M] 기자가 '택배'로만 1주일 살아봤습니다"                                     
## [41] "바이든 사람들은 읽씹 중인데..방미 강경화의 '난센스 외교'"                             
## [42] "동료 의원에 축의금 100만원 건넨 道 의장· 부의장 검찰 송치"                           
## [43] "'술집부터 미행 음주차에 고의 사고' 돈 뜯어낸 20대"                                    
## [44] "[밀착카메라] 쓰레기 쌓이는 '캠핑 명소'..실종된 에티켓"                                
## [45] "이재명 \"연애는 필수, 결혼은 선택?.. 더 이상, 결혼·출산 포기 되어선 안돼\""          
## [46] "美대선불복 와중에 강경화, 트럼프·바이든 양쪽에 손 내밀었다"                          
## [47] "[팩트체크] 영하 70도 백신 유통, 국내에서는 불가능하다?"                               
## [48] "국민의힘, 잡기엔 뜨거운 감자들 '윤·안·금'을 어쩌나"                                 
## [49] "\"담임카톡 못 받아 우는데, 결국 폰 샀죠\" 학부모들 한숨"                              
## [50] "혼전계약서 쓴 트럼프, 멜라니아 이혼땐 14살 아들도 뺏긴다?"
companies
##  [1] "JTBC"       "SBS"        "뉴스1"      "뉴스1"      "MBC"       
##  [6] "오마이뉴스" "연합뉴스"   "MBC"        "JTBC"       "헤럴드경제"
## [11] "연합뉴스"   "JTBC"       "뉴시스"     "MBC"        "KBS"       
## [16] "연합뉴스"   "머니투데이" "KBS"        "연합뉴스"   "KBS"       
## [21] "뉴스1"      "KBS"        "JTBC"       "연합뉴스"   "동아일보"  
## [26] "MBC"        "JTBC"       "KBS"        "채널A"      "한국일보"  
## [31] "연합뉴스"   "경향신문"   "중앙일보"   "서울신문"   "경향신문"  
## [36] "KBS"        "MBC"        "연합뉴스"   "뉴스1"      "MBC"       
## [41] "중앙일보"   "뉴시스"     "뉴시스"     "JTBC"       "머니S"     
## [46] "중앙일보"   "JTBC"       "경향신문"   "국민일보"   "중앙일보"
headline_df <- tibble(headlines, companies) # creates a data frame including two vectors as columns
headline_df
## # A tibble: 50 x 2
##    headlines                                                           companies
##    <chr>                                                               <chr>    
##  1 "520만원짜리 프라다 가방이 5만2천원?..온라인 '들썩'"                JTBC     
##  2 "\"음주운전 안 된다\" 말리던 노모, 아들 차에 참변"                  SBS      
##  3 "이용수 할머니 \"군인이 방으로 끌고 갔을 때 '엄마' 부른 소리 아직 생생\""~ 뉴스1    
##  4 "대검 '한동훈 폭행' 정진웅 직무배제 요청..법무부 검토 중"           뉴스1    
##  5 "\"하루 한 끼로 버텨요\"..20대 청년들이 추락한다"                   MBC      
##  6 "[단독] \"경비원에게 이런 일을, 너무 잔인\" 대학생의 일갈"          오마이뉴스~
##  7 "화이자 CEO, '백신 효과' 발표 당일 \"62억원어치 주식 매각\""        연합뉴스 
##  8 "제트기 동원해 독일로 환자 이송..\"의료붕괴 위기\""                 MBC      
##  9 "트럼프를 아는 이들은 말린다..전 부인 \"골프 치며 살길\""           JTBC     
## 10 "\"아이폰12 너무 비싸 ㅠㅠ\" 90만원→3만원 '똥값'된 아이폰XR 구매 문의 급증! [IT선빵!]"~ 헤럴드경제~
## # ... with 40 more rows
# length() & str_length() apply to headline_df$headlines, grouped by headline_df$companies
tapply(headline_df$headlines, headline_df$companies, length) # returns a table
##       JTBC        KBS        MBC        SBS   경향신문   국민일보      뉴스1 
##          7          6          6          1          3          1          4 
##     뉴시스   동아일보      머니S 머니투데이   서울신문   연합뉴스 오마이뉴스 
##          3          1          1          1          1          7          1 
##   중앙일보      채널A   한국일보 헤럴드경제 
##          4          1          1          1
tapply(headline_df$headlines, headline_df$companies, str_length)
## $JTBC
## [1] 32 32 29 33 30 32 33
## 
## $KBS
## [1] 37 34 38 34 24 39
## 
## $MBC
## [1] 28 28 34 28 36 29
## 
## $SBS
## [1] 28
## 
## $경향신문
## [1] 35 36 30
## 
## $국민일보
## [1] 32
## 
## $뉴스1
## [1] 42 33 43 42
## 
## $뉴시스
## [1] 37 35 30
## 
## $동아일보
## [1] 41
## 
## $머니S
## [1] 45
## 
## $머니투데이
## [1] 28
## 
## $서울신문
## [1] 46
## 
## $연합뉴스
## [1] 37 34 32 36 33 31 39
## 
## $오마이뉴스
## [1] 33
## 
## $중앙일보
## [1] 33 33 33 34
## 
## $채널A
## [1] 37
## 
## $한국일보
## [1] 28
## 
## $헤럴드경제
## [1] 55
headline_characters <- tapply(headline_df$headlines, headline_df$companies, str_length)
headline_characters
## $JTBC
## [1] 32 32 29 33 30 32 33
## 
## $KBS
## [1] 37 34 38 34 24 39
## 
## $MBC
## [1] 28 28 34 28 36 29
## 
## $SBS
## [1] 28
## 
## $경향신문
## [1] 35 36 30
## 
## $국민일보
## [1] 32
## 
## $뉴스1
## [1] 42 33 43 42
## 
## $뉴시스
## [1] 37 35 30
## 
## $동아일보
## [1] 41
## 
## $머니S
## [1] 45
## 
## $머니투데이
## [1] 28
## 
## $서울신문
## [1] 46
## 
## $연합뉴스
## [1] 37 34 32 36 33 31 39
## 
## $오마이뉴스
## [1] 33
## 
## $중앙일보
## [1] 33 33 33 34
## 
## $채널A
## [1] 37
## 
## $한국일보
## [1] 28
## 
## $헤럴드경제
## [1] 55
class(headline_characters)
## [1] "array"
lapply(headline_characters, mean)
## $JTBC
## [1] 31.57143
## 
## $KBS
## [1] 34.33333
## 
## $MBC
## [1] 30.5
## 
## $SBS
## [1] 28
## 
## $경향신문
## [1] 33.66667
## 
## $국민일보
## [1] 32
## 
## $뉴스1
## [1] 40
## 
## $뉴시스
## [1] 34
## 
## $동아일보
## [1] 41
## 
## $머니S
## [1] 45
## 
## $머니투데이
## [1] 28
## 
## $서울신문
## [1] 46
## 
## $연합뉴스
## [1] 34.57143
## 
## $오마이뉴스
## [1] 33
## 
## $중앙일보
## [1] 33.25
## 
## $채널A
## [1] 37
## 
## $한국일보
## [1] 28
## 
## $헤럴드경제
## [1] 55

Let’s apply the function for extracting headlines and companies from the URLs

urls
## [1] "https://news.daum.net/ranking/popular?regDate=20201025"
## [2] "https://news.daum.net/ranking/popular?regDate=20201026"
## [3] "https://news.daum.net/ranking/popular?regDate=20201027"
## [4] "https://news.daum.net/ranking/popular?regDate=20201028"
## [5] "https://news.daum.net/ranking/popular?regDate=20201029"
## [6] "https://news.daum.net/ranking/popular?regDate=20201030"
## [7] "https://news.daum.net/ranking/popular?regDate=20201031"
library(XML)
headline_extractor <- function(url) {
  page <- readLines(url)
  page_parsed <- htmlParse(page)
  headlines <- xpathSApply(page_parsed, headline_xpath, xmlValue)
  return(headlines)
}

headline_list <- lapply(as.list(urls), headline_extractor)
class(headline_list)
## [1] "list"
length(headline_list)
## [1] 7
urls[3]
## [1] "https://news.daum.net/ranking/popular?regDate=20201027"
headline_list[[3]]
##  [1] "'백신 사망' 17세 고교생, 부검서 화학물질 검출..유족 \"억울하다\""                                                            
##  [2] "[단독][취재파일] 잿더미 된 사찰, 알고 보니..부처님 앞 \"할렐루야!\" 외친 '그 여자'"                                          
##  [3] "'화학물질 검출' 고교생..경찰 \"직접 구매 확인\" 가족 \"극단선택 이유없다\""                                                  
##  [4] "[AS뉴스]\"엽기폭행 양진호, 옥중 결혼..한해 수익 2백억\""                                                                     
##  [5] "[단독] '조국 일가 명예훼손' 보수 블로거 \"조 선생님 선처를\""                                                                
##  [6] "'붉은대게' 재고 산더미..공장 문 닫고 조업 포기"                                                                              
##  [7] "성병 숨기고 7개월간 두명과 성관계..20대 집행유예"                                                                            
##  [8] "용인 골프모임 31명 집단확진..가족모임·어린이집서도 새 감염(종합)"                                                           
##  [9] "7억짜리 용인 땅, 300억 됐다..이건희가 건설비 전액 댄 이곳"                                                                   
## [10] "[단독] \"실종 보고받고 지휘한 내용 밝혀라\"<U+22EF> 피격 공무원 형, 청와대에 정보공개 청구"                                  
## [11] "자신과 아내 지키려 흉기든 이웃 제압해 숨지게 한 70대 '무죄'"                                                                 
## [12] "세계최고 수준 천문학적 세금 '폭탄'..세금 때문에 기업 판다"                                                                   
## [13] "트럼프 개인 빚 1조2400억..재선 실패땐 파산 가능성"                                                                           
## [14] "'갑질폭행' 양진호, 옥중결혼 이유..부인 통해 매년 200억 가져간다"                                                             
## [15] "'3000만원 현상금'에 놀라 롤렉스 반환한 범인 \"고가인줄 몰랐어요\"[사건TMI!]"                                                 
## [16] "트럼프 잔고 바닥났다, 바이든은 45억짜리 브래드 피트 광고"                                                                    
## [17] "무면허로 전동킥보드 타다 택시 충돌한 고교생, 사흘만에 사망"                                                                  
## [18] "\"휠 고의 파손? 그런적 없다\" 타이어뱅크 점주 '사과문' 나흘만에 돌변"                                                        
## [19] "문대통령이 윤석열에 메신저 보내?..靑 \"정보 없어 확인 불가\""                                                                
## [20] "시외버스서 승객 너머로 자위행위 촬영 20대 집행유예"                                                                          
## [21] "강경화 \"비자발급 안돼\"→유승준 또 호소문..\"국민이 거부\" 여론 싸늘"                                                       
## [22] "인천 마트 주차장 3층서 승용차 추락..70대 운전자 숨져"                                                                        
## [23] "유튜브 잠깐 출연했다 봉변.. 일상 덮친 이름 모를 '악플'"                                                                      
## [24] "트럼프 극찬한 항체 치료제 실제 써보니 '효과'"                                                                                
## [25] "인천 고교생 사망 원인 \"독감 백신 아닌 독극물\""                                                                             
## [26] "백*원의 원조쌈밥집 등 '자기 이름을 상표로'..성명상표 출원 활발"                                                              
## [27] "파지수집 리어카 끌던 노인, 전복된 승용차에 치여 사망(종합)"                                                                  
## [28] "아프리카서 물개 7000마리 떼죽음 미스터리..대부분 태아 상태"                                                                  
## [29] "백악관 \"대유행 통제 않을 것\" 바이든 \"패배의 백기 흔들어\""                                                                
## [30] "'한동훈과 육탄전' 정진웅, 독직폭행 혐의로 기소(종합)"                                                                        
## [31] "\"왜 더 큰 평수로 옮겨요? 이거 거래허가 못내줍니다\""                                                                        
## [32] "AFP \"EU 회원국 대다수, WTO 총장 선거서 나이지리아 후보 지지\""                                                              
## [33] "중국 공청단 \"한국전쟁 남침 아니다..한 국가 내전\" 궤변(종합)"                                                               
## [34] "의협 다시 집단행동? \"28일까지 의사국시 해결책 내놓지 않으면..\""                                                            
## [35] "이탈리아 언론 또 한국 칭찬..\"첨단기술로 바이러스 잡았다\""                                                                  
## [36] "EU 27개 '몰표' 나이지리아로..WTO 첫 한국인 수장 선출 경고등"                                                                 
## [37] "이건희 회장 병상 6년간 일가 받은 배당금 2.8조"                                                                               
## [38] "[황보선의출발새아침] 박수영\"文 대통령, 둘 다 해임하든 한 사람 해임하든지 결단해야\""                                        
## [39] "쇠징 박힌 신발 신은 채 후배 얼굴 걷어찬 겁 없는 10대"                                                                        
## [40] "[주진우 라이브] 함세웅 신부 \"이건희의 '마누라와 자식 빼고 버려라?'..가족에 매몰된 한계가 삼성의 한계이자 우리 시대의 한계\""
## [41] "1인용 킥보드에 남녀 두명이? 도로 위 '위험천만' 데이트"                                                                       
## [42] "낙동강 하구 이어 도심하천인 부산 온천천에서도 연어 발견"                                                                     
## [43] "\"한국만 아니면 된다\"..고비 때마다 '발목' 잡는 일본"                                                                        
## [44] "[단독] 첫날부터 오작동..2억 원 아끼려다 5명 목숨 잃었다"                                                                     
## [45] "룸살롱서 술판 벌이고 라임 자료 줬는데.. 금감원은 '사적영역'이라며 부실 감찰"                                                 
## [46] "\"한국반도체 인수 검토하라\" 한마디..삼성, 세계적 기업 시발점 됐습니다"                                                      
## [47] "[단독]해외는 좌석 채우는데..한국은 연인도 띄어앉아"                                                                          
## [48] "김봉현이 주장한 술접대, 당사자 전원 \"검사 없었다\""                                                                         
## [49] "독감 백신 접종 뒤 숨진 인천 고교생 형 \"억울함 풀어달라\" 청원(종합)"                                                        
## [50] "중국 신장서 기침·발열없이 137명 집단감염..\"이전 코로나와 다르다\""
company_extractor <- function(url) {
  page <- readLines(url)
  page_parsed <- htmlParse(page)
  companies <- xpathSApply(page_parsed, company_xpath, xmlValue)
  return(companies)
}

company_list <- lapply(urls, company_extractor)
length(company_list)
## [1] 7
urls[7]
## [1] "https://news.daum.net/ranking/popular?regDate=20201031"
company_list[[7]]
##  [1] "머니투데이" "경향신문"   "중앙일보"   "JTBC"       "한국경제"  
##  [6] "연합뉴스"   "연합뉴스"   "연합뉴스"   "연합뉴스"   "뉴스1"     
## [11] "머니투데이" "연합뉴스"   "미디어오늘" "뉴스1"      "뉴스1"     
## [16] "오마이뉴스" "연합뉴스"   "연합뉴스"   "중앙SUNDAY" "서울신문"  
## [21] "뉴스1"      "조선일보"   "연합뉴스"   "서울경제"   "뉴스1"     
## [26] "중앙SUNDAY" "이데일리"   "연합뉴스"   "뉴스1"      "서울신문"  
## [31] "뉴시스"     "아시아경제" "머니투데이" "뉴시스"     "뉴스1"     
## [36] "뉴스1"      "오마이뉴스" "YTN"        "뉴스1"      "MBC"       
## [41] "뉴스1"      "서울신문"   "중앙일보"   "YTN"        "뉴시스"    
## [46] "뉴스1"      "경향신문"   "KBS"        "MBC"        "뉴스1"