您當前的位置:首頁 > 寵物

R語言資料抓取實戰——RCurl+XML組合與XPath解析

作者:由 杜雨 發表于 寵物時間:2017-10-26

經常有小夥伴兒跟我諮詢,在使用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)

R語言資料抓取實戰——RCurl+XML組合與XPath解析

R語言資料抓取實戰——RCurl+XML組合與XPath解析

構建自動化抓取函式,其實挑戰不僅僅是缺失值、不存在值的處理,變數作用域的設定也至關重要,以上自動以函式中使用了兩層for迴圈巢狀,在內層for迴圈中還使用了四個if 判斷,個別欄位的XPath路徑不唯一,為了資料規範,我在XPath中使用了多重路徑“|”。

判斷缺失值(或者填充不存在值)的一般思路就是遍歷每一頁的每一條記錄的XPath路徑,判斷其length,倘若為0基本就可以判斷該對應記錄不存在。

透過設定一個長度為length的預設向量,僅需將那些存在的(長度不為0)記錄透過下標插入對應位置即可,if判斷可以只寫一半(後半部分使用預設的空值)。

至於裡面讓人眼花繚亂的XPath表示式,請參考這一篇,你可以直接去W3C school檢視完整版!

左手用R右手Python系列16——XPath與網頁解析庫

Python網路資料抓取實戰——Xpath解析豆瓣書評

線上課程請點選文末原文連結:

Hellobi Live | 9月12日 R語言視覺化在商務場景中的應用

往期案例資料請移步本人GitHub:

https://

github。com/ljtyduyu/Dat

aWarehouse/tree/master/File

標簽: Class  Text  li  xpathSApply  Span