R爬蟲小白實例教程 - 基於rvest包


封面


注:本文主要參照:手把手 | 教你爬下100部電影數據:R語言網頁爬取入門指南http://mp.weixin.qq.com/s/mIL-p2q7Jp-dhkXkDIrdHQ


一入爬蟲深似海,從此複製是路人。

都說在這一行混,多多少少都要會點爬蟲,畢竟自己動手豐衣足食,本文記錄小鑫第一次練習爬蟲的過程。僅供參考,歡迎各路朋友指點。(E-mail:[email protected]

文末有源代碼及數據。


準備 | 必要的工具

chrome瀏覽器+SelectorGadget插件。

用來獲得網頁中某些部分的相關標籤,若不懂HTML和CSS,強烈安利這個插件。懂HTML和CSS的話,略過,用不着我來教了。

安裝插件之後,在網頁的右上角就會出現圖標,在使用的時候單機一下就可以。

點擊之後,鼠標移動到網頁上就會出現一系列的變化,再單機想要知道標籤的地方,比如標題部分:

截圖1

可以看到,雖然選中了標題,但同時公司名稱和薪資也同樣被選中了,想要取消選中公司名稱很簡單,單機一下公司名稱所在的位置就可以了,如下圖

截圖2

至於不選中薪資,在這裏沒法做到,不過沒關係,在後面可以進行清理。

當然,也可以通過右鍵查看網頁源代碼或者右鍵審查,可以查看標籤,這種方式顯然需要一點HTML基礎。

截圖3

至於R的操作環境,推薦使用RStudio,沒有原因,它就是非常好……


開始 | 準備爬取

網上有看到爬知乎、爬微博、爬智聯招聘、爬拉勾網,各種網站的爬取方式略微不同,小鑫在找了幾個招聘的網站之後,發現BOSS直聘的網址比較簡單,頁面源碼也不復雜,因此,就從這裏開始。

先加載需要的包:

library(xml2)
library(rvest)


首先,分析網址

小鑫搜索的是深圳的數據分析崗位,網址如下:
https://www.zhipin.com/job_detail/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&scity=101280600&source=2

這裏似乎發現不了規律,再點開下一頁呢:https://www.zhipin.com/c101280600/h_101280600/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page=2&ka=page-2

其中個地方引起了我注意:page=2ka=page-2,小鑫試了一下,只要改變這個數字,就能控制翻頁,這個網站最多隻能顯示30頁,每頁15個。所以,不同頁,除了數字不同之外,其他部分都是一模一樣的,那就好辦了,給出一個變量page,然後用for循環:

site1 <- "https://www.zhipin.com/c101280600/h_101280600/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page="
site2 <- "&ka=page-"
page <- 1
for(page in 1:30){
  site <- paste(site1,page,site2,page,sep="")
  webpage <- read_html(site)
  循…
  環…
  內…
  容…
  …

}

site1和site2控制着整個網址的固定部分,page控制網址的變動部分,從1循環到30。

循環中的第一個語句,用paste將site1、site2、page連接成一個完整的網址。

第二句:將網頁信息保存到webpage這個變量裏,以後的所有抓取動作,都是從這個變量裏來的。


然後,確定抓取內容

這一步主要是回到網頁中來:

截圖4

可以發現,在每條招聘信息裏,可以爬取這些內容:標題、薪資、公司名、地點、經驗要求、學歷要求、行業、融資/上市情況、公司規模、關鍵詞、聯繫人及其崗位。

不同的內容在不同的標籤裏面,這裏僅僅拿部分內容舉例說明,其他信息的爬取都是大同小異的,詳見附件源碼或聯繫小鑫(E-mail:[email protected]

值得一提的是,不同招聘信息的關鍵詞數量不同,所以,我就單獨把關鍵詞作爲另一項內容保存了起來,用於後面做詞雲。


OK | 開始爬取

先爬取標題和公司名稱,用谷歌瀏覽器和插件,可得知標題和公司名稱所在的標籤分別是:.info-primary .name.company-text .name,使用如下語句:

name1 <- html_nodes(webpage,'.info-primary .name')# 抓取標題
name2 <- html_nodes(webpage,'.company-text .name')# 抓取公司名稱

查看name1和name2。

截圖5

可以看出,已經爬取了正確的信息,只是需要刪除那些標籤和不需要的內容,接下來的思路就很簡單了,使用gsub函數,將不必要的內容替換成空。

比如:< h3 class=”name”>、< span class=”red”>、< /span>\n這些標籤。

name1 <- gsub("<h3 class=\"name\">","",name1)
name1 <- gsub(" <span class=\"red\">.*","",name1)
name1 <- gsub("</span>\n</h3>","",name1)
name1 <- gsub("</h3>","",name1)
titlename <- as.data.frame(name1)

name2 <- gsub("<h3 class=\"name\">","",name2)
name2 <- gsub("</h3>","",name2)
companyname <- as.data.frame(name2)

這個時候,再看一下數據內容:

截圖6

保存數據:

bossdata <- data.frame(companyname,titlename)
bossdata

可以看出,能完成到這一步,基本上算是完成了90%,後面的思路都是大同小異的,注意變換一下形式就OK了,但是還是有一個小問題,就是剩下的10%。

繼續 | 最後一小步

然後就是抓取薪資,這一步也很簡單,直接上代碼:

# 抓取薪資
salary <- html_nodes(webpage,'.red')
salary <- gsub("<span class=\"red\">","",salary)
salary <- gsub("</span>","",salary)

bossdata <- cbind(bossdata,salary)
bossdata

問題出在了這一步:

# 抓取要求及公司信息
message <- html_nodes(webpage,'p')
message <- message[-1]
message <- gsub("<p>","",message)
message <- gsub("<em class=\"vline\"></em>",",",message)
message <- gsub("</p>","",message)
message <- gsub("<img",",",message)
message

截圖7

可以看得出來,問題就在於“地點、工作經驗、學歷”在同一個位置,“行業、融資/上市情況、公司規模”也在同一個位置,這樣的情況下,就不能按照上面的方法來操作了,其實也不難,只要設置一個循環,重點就解決了。

# 先設置三個變量,分別讀取message中的不同數據
xx <- c(1:as.numeric(length(message)/3))
yy <- c(1:as.numeric(length(message)/3))
zz <- c(1:as.numeric(length(message)/3))

# xx用來存放message中的地點、經驗、學歷要求
k1 <- 1
l1 <- 1
for(k1 in seq(1:(length(message)/3))){
  xx[k1] <- message[l1]
  l1 <- k1*3+1
}
xx

# 可以看出xx雖然提取正確了,但是還需要進一步處理
xx <- as.data.frame(xx)
xx <- apply(as.data.frame(xx),1,strsplit,",")
xx <- as.data.frame(xx)
xx[1,]

# 分別提取xx中的地點,經驗,學歷
place <- t(as.data.frame(xx[1,]))
experience <- t(as.data.frame(xx[2,]))
education <- t(as.data.frame(xx[3,]))

# 合併數據框
bdata <- data.frame(place,experience,education)
names(bdata) = c("place", "experience", "education")
bossdata <- data.frame(bossdata, bdata)
bossdata

後面需要提取行業、融資/上市情況、公司規模等信息,都是採用相同的方法,具體內容,可以查看附件代碼。至此,最簡單的一個爬蟲就寫好了。

一般來說,行業、融資/上市情況、公司規模這三個是在一起的,但是有兩條信息,只有兩個內容,如下圖:

截圖8

截圖9

我的解決方法是:找到相應的位置,然後在那個地方填補一個缺失值NA,比如,在小鑫運行程序的時候,他們處在第一頁的第十一和第十五條數據,因此,小鑫使用如下代碼:

if(page == 1){
  financing11 <- financing[11,]
  financing15 <- financing[15,]

  financing[11,] <- NA
  financing[15,] <- NA
  companysize[11,] <- financing11
  companysize[15,] <- financing15
}
else {
  print("Hello World")
}

但是這種方法有很大的弊端,小鑫在寫這篇文章的時候,這兩條信息又跑到了第二頁第五條和第十三條。因此,第一行的代碼就變成了page == 2,第二三行分別是:financing5 <- financing[5,]
financing13 <- financing[13,]

小鑫在想是不是可以讓R自動識別他們的位置,然後填充NA,甚至於在以後出現第三條、第四條類似信息的時候,也能識別出空缺的位置,然後進行自動填補呢?

應該是可以的,不過小鑫現在才疏學淺,還沒那個技術。待小鑫技術學成,再奉上文章。

——2017年5月19日

【END】


源代碼及爬取後數據

鏈接:http://pan.baidu.com/s/1jI5Lmke

密碼:0cjv

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章