R語言資料抓取實戰——RCurl+XML組合與XPath解析,rcurlxpath
杜雨,EasyCharts團隊成員,R語言中文社區專欄作者,興趣方向為:Excel商務圖表,R語言資料視覺效果,地理資訊資料視覺效果。個人公眾號:資料小魔方(ID:datamofang) ,“資料小魔方”創始人。
經常有小夥伴兒跟我諮詢,在使用R語言做網路資料抓取時,遇到空值和缺失值或者不存在的值,應該怎麼辦。
因為我們大多數場合從網路抓取的資料都是關係型的,需要欄位和記錄一一對應,但是html文檔的結構千差萬別,代碼紛繁複雜,很難保證提取出來的資料開始就是嚴格的關係型,需要做大量的缺失值、不存在內容的判斷。
如果未經處理資料是關係型的,但是你抓取來的是亂序的欄位,記錄無法一一對應,那麼這些資料通常價值不大,今天我以一個小案例(跟昨天案例相同)來示範,如何在網頁遍曆、迴圈嵌套中設定邏輯判斷,適時的給缺失值、不存在值填充預設值,讓你的爬蟲代碼更穩健,輸出內容更規整。
載入擴充包:
#載入包:
library("XML")
library("stringr")
library("RCurl")
library("dplyr")
library("rvest")
#提供目標網址連結/前序參數
url<-'https://read.douban.com/search?q=Python'
header =c('User-Agent'='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36')
構建抓取函數:
getcontent<-function(url){
#這個資料框是為最終的資料匯總返回提供的初始值 myresult=data.frame()
#這些空向量是遍曆單頁書籍記錄提供的初始值 title=author=category=subtitle=eveluate_nums=rating=price=c()
#開始遍曆網頁 for (page in seq(0,3)){
#遍曆不同頁面 link<-paste0(url,'&start=',page*10)
#請求網頁並解析 content<-getURL(link,httpheader=header) %>% htmlParse() #計算單頁書籍條目數 length<-content %>% xpathSApply(.,"//ol[@class='ebook-list column-list']/li") %>% xmlSize()
###提取標題: title<-content %>% xpathSApply(.,"//ol/li//div[@class='title']/a| //ol/li//h4/a",xmlValue) %>% c(title,.)
###提取圖書類別: category=content %>% xpathSApply(.,"//span[@class='category']/span[2]/span | //p[@class='category']/span[@class='labled-text'] | //div[@class='category']",xmlValue) %>% c(category,.)
###提取作者/副標題/評論數/評分/價格資訊: author_text=subtitle_text=eveluate_nums_text=rating_text=price_text=rep('',length)
for (i in 1:length){
###提取作者 author_text[i]=content %>% xpathSApply(.,sprintf("//li[%d]//p[@class]//span/following-sibling::span/a | //li[%d]//div[@class='author']/a",i,i),xmlValue) %>% paste(.,collapse='/')
###考慮副標題是否存在 if (content %>% xpathSApply(.,sprintf("//ol/li[%d]//p[@class='subtitle']",i),xmlValue) %>% length!=0){ subtitle_text[i]=content %>% xpathSApply(.,sprintf("//ol/li[%d]//p[@class='subtitle']",i),xmlValue) }
###考慮評價是否存在: if (content %>% xpathSApply(.,sprintf("//ol/li[%d]//a[@class='ratings-link']/span",i),xmlValue) %>% length!=0){ eveluate_nums_text[i]=content %>% xpathSApply(.,sprintf("//ol/li[%d]//a[@class='ratings-link']/span",i),xmlValue) }
###考慮評分是否存在: if (content %>% xpathSApply(.,sprintf("//ol/li[%d]//div[@class='rating list-rating']/span[2]",i),xmlValue) %>% length!=0){ rating_text[i]=content %>% xpathSApply(.,sprintf("//ol/li[%d]//div[@class='rating list-rating']/span[2]",i),xmlValue) }
###考慮價格是否存在: if (content %>% xpathSApply(.,sprintf("//ol/li[%d]//span[@class='price-tag ']",i),xmlValue) %>% length!=0){ price_text[i]=content %>% xpathSApply(.,sprintf("//ol/li[%d]//span[@class='price-tag ']",i),xmlValue) } }
#拼接以上通過下標遍曆的書籍記錄數 author=c(author,author_text) subtitle=c(subtitle,subtitle_text) eveluate_nums=c(eveluate_nums,eveluate_nums_text) rating=c(rating,rating_text) price=c(price,price_text) #列印單頁任務狀態 print(sprintf("page %d is over!!!",page)) }
#構建資料框 myresult=data.frame(title,subtitle,author,category,price,rating,eveluate_nums)
#列印總體任務狀態 print("everything is OK")
#返回最終匯總的資料框 return(myresult)}
提供url連結並運行我們構建的抓取函數:
myresult=getcontent(url)
[1] "page 0 is over!!!"
[1] "page 1 is over!!!"
[1] "page 2 is over!!!"
[1] "page 3 is over!!!"
[1] "everything is OK"
查看資料結構:
str(myresult)
規範變數類型:
myresult$price<-myresult$price %>% sub("元|免費","",.) %>% as.numeric()myresult$rating<-as.numeric(myresult$rating)myresult$eveluate_nums<-as.numeric(myresult$eveluate_nums)
預覽資料:
DT::datatable(myresult)
構建自動化抓取函數,其實挑戰不僅僅是缺失值、不存在值的處理,變數範圍的設定也至關重要,以上自動以函數中使用了兩層for迴圈嵌套,在內層for迴圈中還使用了四個if 判斷,個別欄位的XPath路徑不唯一,為了資料規範,我在XPath中使用了多重路徑“|”。
判斷缺失值(或者填充不存在值)的一般思路就是遍曆每一頁的每一條記錄的XPath路徑,判斷其length,倘若為0基本就可以判斷該對應記錄不存在。
通過設定一個長度為length的預設向量,僅需將那些存在的(長度不為0)記錄通過下標插入對應位置即可,if判斷可以唯寫一半(後半部分使用預設的空值)。
至於裡面讓人眼花繚亂的XPath運算式,請參考這一篇,你可以直接去W3C school查看完整版!
左手用R右手Python系列16——XPath與網頁解析庫
線上課程請點擊文末原文連結:
往期案例資料請移步本人GitHub:
https://github.com/ljtyduyu/DataWarehouse/tree/master/File
相關課程推薦
R語言爬蟲實戰案例分享:
網易雲課堂、知乎live、今日頭條、B站視頻
分享內容:本次課程所有內容及案例均來自於本人平時學習練習過程中的心得和筆記總結,希望藉此機會,將自己的爬蟲學習曆程與大家分享,並為R語言的爬蟲生態改善以及工具的推廣,貢獻一份微薄之力,也是自己爬蟲學習的階段性總結。
☟☟☟ 猛戳閱讀原文,即刻加入課程。