首先感謝[無魚二餅]同學(xué)的文章《R語言學(xué)習(xí):使用rvest包抓取網(wǎng)頁數(shù)據(jù)》,本文參考其操作過程。
</br>
一、學(xué)會了看網(wǎng)頁源代碼
01.我使用Chrom瀏覽器,在天貓上搜索筆記本電腦,然后選擇品牌為Lenovo/聯(lián)想。
02.按下CTRL+SHIFT+C。當(dāng)鼠標(biāo)放到該寶貝頁面的任何位置是,可以看到相應(yīng)的源代碼。而寶貝的圖片、價格、品牌名稱、賣家以及月銷量等數(shù)據(jù)都是包含在<div class="product-iWrap">...</div>塊中。
03.每一個div都可以展開。每一條都有對應(yīng)的網(wǎng)頁顯示,當(dāng)點(diǎn)擊源代碼時,網(wǎng)頁上顯示一層覆膜蓋在相關(guān)的文字和圖片上,表明這兩個是對應(yīng)的。
</br>
二、啟動R進(jìn)行工作
01.安裝rvest并加載rvest包
# 加載包
library(rvest)
02.保存搜索鏈接對象到gurl。即把需要抓取的網(wǎng)頁地址復(fù)制過來。
gurl<-"https://list.tmall.com/search_product.htm?spm=a220m.1000858.1000720.2.JVFBWt&cat=50024399&brand=11119&q=%B1%CA%BC%C7%B1%BE%B5%E7%C4%D4&sort=s&style=g&from=sn_1_brand-qp&active=1#J_crumbs"
03.抓取數(shù)據(jù)對象保存到SCdata中。即從源代碼中提取出有用的部分——"div.product-iWrap"(相當(dāng)于是一個目錄,我們從整個源代碼塊中篩選出我們需要的目錄)。
#%>%是管道操作符,意思是把左邊的操作結(jié)果作為參數(shù)傳遞給右邊的函數(shù)。
#div.product-iWrap是CSS選擇器的語法,即div class="div.product-iWrap"
> SCdata <-gurl %>%
+ read_html(encoding="GBK")%>%#讀取gurl的鏈接,并指定編碼為gbk.
+ html_nodes("div.product-iWrap")#篩選出所有包含在<div class="product-iWrap">...</div>塊的內(nèi)容
運(yùn)行結(jié)果如下(僅為一小部分):
>SCdata
{xml_nodeset (60)}
[1] <div class="product-iWrap">\n <div class="productImg-wrap">\n<a href="http://detail.tmall.com/item.htm?id=5340786229 ...
[2] <div class="product-iWrap">\n <div class="productImg-wrap">\n<a href="http://detail.tmall.com/item.htm?id=5448064555 ...
[3] <div class="product-iWrap">\n <div class="productImg-wrap">\n<a href="http://detail.tmall.com/item.htm?id=5431560989 ...
[4] <div class="product-iWrap">\n <div class="productImg-wrap">\n<a href="http://detail.tmall.com/item.htm?id=5445795234 ...
[5] <div class="product-iWrap">\n <div class="productImg-wrap">\n<a href="http://detail.tmall.com/item.htm?id=5425410474 ...
[6] <div class="product-iWrap">\n <div class="productImg-wrap">\n<a href="http://detail.tmall.com/item.htm?id=5475609243 ...
04.從對象SCdata中繼續(xù)篩選,獲取賣家名稱等數(shù)據(jù)。
需要掌握幾個函數(shù)的基本使用:
#html_attr("data-nick")是從html_nodes()篩選出的標(biāo)簽中,查找data-nick屬性的值。
#gsub()是字符串查找替換的函數(shù),pattern是指定用來查找的正則表達(dá)式。
#html_nodes("p.productTitle>a[title]"),">"指定的篩選條件的標(biāo)簽
#html_text()只抓取<標(biāo)簽>內(nèi)容</標(biāo)簽>中的內(nèi)容部分
#抓取賣家店鋪名稱和ID
> SCdata <-gurl %>%
+ read_html(encoding="GBK")%>%#讀取gurl的鏈接,并指定編碼為gbk.
+ html_nodes("div.product-iWrap")#篩選出所有包含在<div class="product-iWrap">...</div>塊的內(nèi)容
> #抓取賣家昵稱和ID
> sellerNick<- SCdata %>% html_nodes("p.productStatus>span[class]") %>%
+ html_attr("data-nick")
> sellerID<- SCdata %>% html_nodes("p.productStatus>span[data-atp]") %>%
+ html_attr("data-atp") %>%
+ gsub(pattern="^.*,",replacement="")
> #抓取寶貝名稱等數(shù)據(jù)
> itemTitle<- SCdata %>% html_nodes("productTitle>a[title]") %>%
+ html_attr("title")#暫時未能輸出結(jié)果,先放下,后面再請教作者并嘗試。
> itemID<- SCdata %>%html_nodes("p.productStatus>span[class]") %>%
+ html_attr("data-item")
> price<- SCdata %>% html_nodes("em[title]") %>%
+ html_attr("title") %>%
+ as.numeric
> volume<- SCdata %>% html_nodes("span>em") %>%
+ html_text
> #最后保存成數(shù)據(jù)框?qū)ο蟛⒋姹P備用,以及寫入csv文件
> options(stringsAsFactors = FALSE) #設(shè)置字符串不自動識別為因子
>
> itemData<-data.frame(sellerNick=sellerNick,
+ sellerID=sellerID,
+ itemID=itemID,
+ price=price,
+ volume=volume)
> save(itemData,file = "E:/R語言筆記/R語言第七章/itemData.rData")
> write.csv(itemData,file = "E:/R語言筆記/R語言第七章/itemData.csv")
</br>
總體代碼匯總?cè)缦拢?/strong>
> install.packages("rvest")
> # 加載包
> library(rvest)
載入需要的程輯包:xml2
> #保存搜索鏈接對象到gurl
> gurl<-"https://list.tmall.com/search_product.htm?spm=a220m.1000858.1000720.2.JVFBWt&cat=50024399&brand=11119&q=%B1%CA%BC%C7%B1%BE%B5%E7%C4%D4&sort=s&style=g&from=sn_1_brand-qp&active=1#J_crumbs"
> #抓取數(shù)據(jù)對象保存到SCdata中
> #%>%是管道操作符
> #意思是把左邊的操作結(jié)果作為參數(shù)傳遞給右邊的命令
> #div.product-iWrap是CSS選擇器的語法,即div class="div.product-iWrap"
> SCdata<-gurl %>%
+ read_html(encoding="GBK")%>%#讀取gurl的鏈接,并指定編碼為gbk.
+ html_nodes("div.product-iWrap")#篩選出所有包含在<div class="product-iWrap">...</div>塊的內(nèi)容
>
> #從對象SCdata繼續(xù)篩選,獲取賣家名稱等數(shù)據(jù)
> #html_attr("data-nick")是從html_nodes()篩選出的標(biāo)簽中,查找data-nick屬性的值。
> #gsub()是字符串查找替換的函數(shù),pattern是指定用來查找的正則表達(dá)式。
> #html_nodes("p.productTitle>a[title]"),">"指定的篩選條件的標(biāo)簽
> #html_text()只抓取<標(biāo)簽>內(nèi)容</標(biāo)簽>中的內(nèi)容部分
>
> #抓取賣家昵稱和ID
> sellerNick<- SCdata %>% html_nodes("p.productStatus>span[class]") %>%
+ html_attr("data-nick")
> sellerID<- SCdata %>% html_nodes("p.productStatus>span[data-atp]") %>%
+ html_attr("data-atp") %>%
+ gsub(pattern="^.*,",replacement="")
>
> #抓取寶貝名稱等數(shù)據(jù)
> itemTitle<- SCdata %>% html_nodes("productTitle>a[title]") %>%
+ html_attr("title")#暫時未能輸出結(jié)果,先放下,后面再請教作者并嘗試。
> itemID<- SCdata %>%html_nodes("p.productStatus>span[class]") %>%
+ html_attr("data-item")
> price<- SCdata %>% html_nodes("em[title]") %>%
+ html_attr("title") %>%
+ as.numeric
> volume<- SCdata %>% html_nodes("span>em") %>%
+ html_text
>
>
> #最后保存成數(shù)據(jù)框?qū)ο蟛⒋姹P備用,以及寫入csv文件
> options(stringsAsFactors = FALSE) #設(shè)置字符串不自動識別為因子
>
> itemData<-data.frame(sellerNick=sellerNick,
+ sellerID=sellerID,
+ itemID=itemID,
+ price=price,
+ volume=volume)
> save(itemData,file = "E:/R語言筆記/R語言第七章/itemData.rData")
> write.csv(itemData,file = "E:/R語言筆記/R語言第七章/itemData.csv")
</br>
三、進(jìn)行數(shù)據(jù)分析
生成了itemData數(shù)據(jù)為.csv文件,在預(yù)覽是提示需要保存為.excel文件。在本例中可以直接進(jìn)行分析。本例只抓取了天貓上一個頁面的綜合數(shù)據(jù)(筆記本電腦-聯(lián)想品牌,未使用其它篩選條件,保持天貓首頁給出數(shù)據(jù)的原始性),數(shù)據(jù)量較小,不具有充分的代表性和實(shí)際意義,僅為實(shí)踐操作。
01.直接進(jìn)行預(yù)處理
參照實(shí)踐課程的處理方式,刪除所有含有缺失數(shù)據(jù)的行。雖然數(shù)據(jù)樣本可能是完整的,但是在分析數(shù)據(jù)是嚴(yán)謹(jǐn)細(xì)致是必須的。使用na.omit()函數(shù)可以刪除所有含有缺失數(shù)據(jù)的行,可以使用newData<-na.omit(itemData)
。本例在抓取數(shù)據(jù)生成數(shù)據(jù)框的時候,已經(jīng)進(jìn)行了驗(yàn)證。
> itemData<-itemData[!is.na(itemData$price),] #保留未缺失價格的數(shù)據(jù)
> itemData
也可采取同樣的方法對銷售的數(shù)量volume進(jìn)行操作,目的是保證后期重要數(shù)據(jù)的有效性。
02.進(jìn)行列名重命名工作
使用fix()函數(shù)調(diào)出編輯器即可。或者使用names()函數(shù)來重命名。
03.處理銷售數(shù)量列
本例不涉及日期。本例子中較為有用的信息主要是price、volume、sellerNick。本例需要處理的是volume,從中分離出銷售數(shù)量,即從384筆中提取出384。具體使用字符串中的str_extract()函數(shù):
> library(stringr)#載入字符串
> Newvolume<-str_extract(itemData$volume, "\\d+")#注意d后面的+號,否則只會輸出每個銷售數(shù)量中第一個數(shù)字,
#+號的意思是輸出識別到所有數(shù)字。
> Newvolume
[1] "363" "493" "123" "491" "365" "929" "670" "439" "143" "98"
[11] "153" "1465" "1270" "110" "522" "128" "473" "277" "345" "161"
[21] "215" "87" "64" "190" "116" "107" "38" "567" "126" "85"
[31] "201" "359" "106" "13" "92" "147" "2" "167" "79" "66"
[41] "51" "56" "61" "106" "11" "19" "38" "69" "27" "60"
[51] "14" "17" "12" "25" "33" "11" "44" "2" "36" "14"
> NewData<-cbind(itemData,Newvolume)#把篩選出來的銷售數(shù)量添加到原數(shù)據(jù)集中。
> save(NewData,file = "E:/R語言筆記/R語言第七章/NewData.rData")
> write.csv(NewData,file = "E:/R語言筆記/R語言第七章/NewData.csv")
打開輸出的文件Newdata查看了一下,數(shù)據(jù)轉(zhuǎn)換正常。
04.對Newvolume和price進(jìn)行類型轉(zhuǎn)換。
> class(NewData$newvolume)#先查看類別
[1] "character"
> class(NewData$price) #先查看類別
[1] "numeric"
> NewData$newvolume<-as.numeric(NewData$newvolume)#進(jìn)行轉(zhuǎn)換
> NewData$price<-as.numeric(NewData$price) #進(jìn)行轉(zhuǎn)換
> class(NewData$newvolume)#進(jìn)行再次查看
[1] "numeric"
> class(NewData$price) #進(jìn)行再次查看
[1] "numeric"
05.排序
可以使用order()函數(shù)對一個數(shù)據(jù)框進(jìn)行排序,按照Newvolume對數(shù)據(jù)進(jìn)行升序排序。
NewData<-NewData[order(NewData$newvolume),]#排序后備用
</br>
四、對數(shù)據(jù)的分析運(yùn)用
目的一:計(jì)算樣本中聯(lián)想電腦的均價,銷售數(shù)量的均值,并以此計(jì)算出總樣本平均的銷售價格。
目的二:銷售總金額
目的三:繪制價格-銷售數(shù)量圖(折線圖和點(diǎn)圖)
01.計(jì)算聯(lián)想電腦均價
> shopkpi1<-nrow(NewData)#
> shopkpi1#計(jì)算抓取總的店鋪數(shù)量(包括重復(fù)的店鋪,因?yàn)榇嬖趦r格不同、銷售數(shù)量不同的情況)
[1] 60
> totalPrice<-sum(NewData$price,na.rm = TRUE)#求和
> averagePrice<-totalPrice/shopkpi1
> averagePrice#求出均價
[1] 4383.617
這里計(jì)算了一下聯(lián)系電腦價格四分位數(shù):
可以看到樣本中求取得平均價格4383.617比60%的臨界點(diǎn)小,比40%的臨界點(diǎn)大,但更靠近60%的臨界點(diǎn),也就是說均價處于中等偏上位置。
> y<-quantile(NewData$price,c(.8,.6,.4,.2))
> y#求取分位數(shù)
80% 60% 40% 20%
5179 4539 3979 3479
> z<-median(NewData$price)
> z#價格中位數(shù)
[1] 4324
> min(NewData$price)#求取最小值
[1] 2488
> max(NewData$price)#求取最大值
[1] 8399
> #繪制箱線圖
> boxplot(NewData$price,main="聯(lián)想電腦價格箱線圖",ylab="Price")
02.計(jì)算銷售數(shù)量的均值
> shopkpi1<-nrow(NewData)#獲取行數(shù)
> shopkpi1
[1] 60
> totalVolume<-sum(NewData$newvolume,na.rm = TRUE)#求取銷售數(shù)量總和,即共有多少筆交易
> averageVolume<-totalVolume/shopkpi1
> totalVolume
[1] 12495
> averageVolume#店鋪的平均銷量為208.25筆交易(表示為已經(jīng)收到貨,
#且確認(rèn)付款的交易,不包括未確認(rèn)收獲的交易情況,同時這也不是一個完整月的交易量,數(shù)據(jù)截止到2017.04.23)
[1] 208.25
03.計(jì)算截止目前四月份銷售總金額
> totalmoney<-sum(NewData$price*NewData$newvolume,na.rm = TRUE)
> totalmoney#抓取得頁面中聯(lián)系電腦總銷售金額將近五千萬
[1] 48700684
04繪制價格-銷量圖
a.繪制最優(yōu)擬合圖
> #繪制最優(yōu)擬合曲線圖
> attach(NewData)
> plot(NewData$price,NewData$newvolume)
> abline(lm(NewData$price~NewData$newvolume))
> title("聯(lián)想電腦價格和銷售量關(guān)系圖")
> detach(NewData)
看來市場經(jīng)濟(jì)的規(guī)律是對的,需求第一定律說:無論何時何地,價格提高,商品的需求量就減少,價格降低到一定程度,需求量就一定會增加。
b.繪數(shù)點(diǎn)圖
dotchart(NewData$newvolume,labels = NewData$price,cex = .7,
main = "銷售數(shù)量和價格關(guān)系",
xlab="銷售數(shù)量")
關(guān)于點(diǎn)數(shù)圖中,想進(jìn)行分類別處理,目前還在探索中,后續(xù)會更新。