2016年9月22日 星期四

超簡單爬蟲教學-使用R軟體的rvest套件抓網站資料(基礎篇)

前言
以前覺得爬蟲就是要很會寫程式才能做的事,但這個暑假實習時需要用到爬蟲,不得不自己學,而我本身用R,網路看別人的分享文發現沒那麼難,不需要很會寫程式,簡易的爬蟲很快就可以上手了。多簡單呢?就算第一次用R也看得懂! 就讓我們看下去吧。
  這篇介紹四個部分:

1.安裝並執行rvest套件
2.安裝SelectorGadge CSS選擇器&選擇要爬取的網站內容
3.1開始寫R爬取你要的網頁資訊-爬新聞標題
3.2 想爬新聞標題的超連結
4.magrittr介紹-讓你程式碼更簡潔的好用套件

首先我們需要安裝爬蟲的套件 rvest
每行程式碼的說明會附在程式碼的#後面,複製是不會執行的。

1.安裝並執行rvest套件


install.packages('rvest')  #安裝rvest套件
library(rvest) #開啟rvest套件
2.安裝SelectorGadge CSS選擇器&選擇要爬取的網站內容
這是一個可以讓你點選你要爬網頁上甚麼資訊的好用小軟體,
 SelectorGadge安裝連結。
接著以自由電子報棒球版為選擇示範,


Step1.點選右上角的放大鏡SelectorGadge工具
Step2.我想要抓中間的主要新聞的標題,點一下標題會顯示成綠色和黃色的,表示你有選到
Step3.若不想要抓的右上角的熱門新聞,點一下就會顯示紅色,表示不會抓到。
Step4.看到下面的紅框處有程式碼,這就是很重要你等下會用到的程式碼,複製他。
Step5.要重新選擇,按Clear,要關掉選擇模式,按右邊的叉叉。


3.1開始寫R爬取你要的網頁資訊-爬新聞標題
title=read_html("http://sports.ltn.com.tw/baseball")   
#輸入你要爬取網頁的網址,爬取此網頁的html資訊 

title=html_nodes(title,".boxTitle .listA .list_title")   
#函數首先代入剛剛的網頁資訊,逗號後就是很重要的輸入你前面使用Selector複製的程式碼,他會從此網頁中篩選出剛剛你想要爬的新聞標題。 

title=html_text(title)   # 只篩選出文字
title=iconv(title,"UTF-8")  #若是文字出現亂碼,將格式改成可以辨識的形式
#來看看跑出的結果
title
 [1] "中職》鋒哥引退好風光 日韓敵人跨海祝福"              
 [2] "中職》向陳金鋒致敬 Lamigo宣布52號退休"              
 [3] "中職》發表引退感言 陳金鋒:我愛你們!"              
 [4] "中職》林哲瑄:好希望鋒哥把球打來我這邊"             
 [5] "中職 Live》陳鏞基本季第20轟   統一11:6擊敗兄弟"    
 [6] "中職Live》鋒哥引退賽完美落幕 犀牛13:9猿"           
 [7] "中職》鋒哥引退賽 4支0、3K抱憾收場"                  
 [8] "中職》高國輝最速百轟 桃園球場貢獻第2多"             
 [9] "MLB》向洋基球迷說拜拜 老爹:跪求噓爆我"             
[10] "中職》二壘審跑壘卡位「被觸殺」 統一獅雙盜壘離奇得分"
3.2 想爬新聞標題的超連結-
url=read_html("http://sports.ltn.com.tw/baseball") #爬取同一個網頁
url=html_nodes(url,".boxTitle .listA a")  
#這裡要注意,使用Selector選區塊時不要按在標題上,要點在旁邊,框框會比點在標題上面大喔,
#所以所選出來的程式碼和剛剛的不一樣。

url=html_attr(url,"href")  #選擇html頁面中的連結網址的部分(若使用剛剛爬標題的Selector碼會跑不出來,出現NA)
#看跑出的結果,現這頁20篇新聞的連結囉

[1] "news/breakingnews/1831833" "news/breakingnews/1831833" "news/breakingnews/1831860"
 [4] "news/breakingnews/1831860" "news/breakingnews/1831841" "news/breakingnews/1831841"
 [7] "news/breakingnews/1831835" "news/breakingnews/1831835" "news/breakingnews/1831825"
[10] "news/breakingnews/1831825" "news/breakingnews/1831791" "news/breakingnews/1831791"
[13] "news/breakingnews/1831800" "news/breakingnews/1831800" "news/breakingnews/1831768"
[16] "news/breakingnews/1831768" "news/breakingnews/1831750" "news/breakingnews/1831750"
[19] "news/breakingnews/1831618" "news/breakingnews/1831618"
4.magrittr介紹-讓你程式碼更簡潔的好用套件
覺得上面的程式碼太冗,需要指定參數(table,url)太多次嗎?
 #先安裝magrittr套件
install.packages('magrittr')
library(magrittr)
#爬棒球新聞標題-程式碼精簡版
title=read_html("http://sports.ltn.com.tw/baseball/") %>% 
html_nodes(".boxTitle .listA .list_title") %>% 
html_text() %>% iconv("UTF-8")

#只要在開頭指定title,後面幾行只要加上%>%,就不用再指定,
#中間的函數也不用輸入title,此套件會自動把前面的函數指定到下個函數的第一個參數中,
#如此程式碼就變得簡潔許多啦
----------------------------------------------------------------------------------------------------------------------

以上是最基本的爬蟲單個網頁,下一篇會介紹
1.如果想要一次爬很多頁怎麼做?
2.出現error
3.想爬其他attr屬性的網頁資訊



  寫這篇分享文主要是因為之前工作內容而需要爬蟲,從零開始花時間各方參考學習終於會一點技巧,所以分享心得給也想開始用R學爬蟲的人參考。



參考資料:
http://blog.bryanbigdata.com/2014/05/r.html
https://rpubs.com/SatoshiLiang/159348
https://stat4701.github.io/edav/2015/04/02/rvest_tutorial/
http://www.jerrynest.com/big-data-workshop-r-crawler/


超簡單爬蟲教學-使用R軟體的rvest套件抓網站資料(問題及進階篇)

這篇介紹爬蟲時可能碰到的問題
1.爬網頁時出現Error in open.connection(x, "rb") :  Failure when receiving data from the peer
2.如果想要一次爬很多頁的資訊怎麼做?
3.想爬其他除了網址外 attr屬性的網頁資訊
---------------------------------------------------------------------------------

1.爬網頁時出現Error in open.connection(x, "rb") :  Failure when receiving data from the peer
此時只要使用先把網頁下載的方法就可以解決了,這裡以爬mobile01的智慧型手機討論區標題為例,用前一篇的直接爬蟲方法會出現錯誤。







#爬mobile01的智慧型手機綜合討論區出現以下錯誤
read_html("http://www.mobile01.com/topiclist.php?f=61") %>% html_nodes("topic_gen") %>% html_text() %>% iconv("UTF-8")
Error in open.connection(x, "rb") : 
  Failure when receiving data from the peer
使用download.file()這個函數先下載網頁再爬蟲

download.file("http://www.mobile01.com/topiclist.php?f=61","D:/smartphone.html")
#此函數第一個參數輸入你想爬的網頁,第二個參數輸入你要下載此網頁到你電腦的路徑及檔名和檔案格式

trying URL 'http://www.mobile01.com/topiclist.php?f=61'
Content type 'text/html; charset=utf-8' length unknown
downloaded 52 KB
#輸入完出現這個表示下載成功

read_html("D:/smartphone.html") #之後爬網頁再輸入你剛剛下載的路徑到read_html裡面就可以成功爬此網頁了

2.
爬蟲就是要爬很多頁,不然手動複製就好啦!
所以我們可以善用for迴圈一次爬很多頁的資訊。
以剛剛的mobile01智慧型手機討論區為例,若我想要一次爬20頁的每篇標題怎麼做?

先下載20頁的mobile01網頁到電腦


for (i in 1:20){
loc=paste("http://www.mobile01.com/topiclist.php?f=61&p=",i,sep="")

#觀察到Mobile01討論區的網址,第一頁和第二頁只有最後面的p=1和=2的差別,所以使用paste()函數
#搭配for迴圈來產生第1到第20頁的網址。paste是個連接字串的函數,
#最後一個參數sep設定不要有空格就可以讓前面所有參數裡的字串連在一起,
#網路上有其他人的字串相關函數詳細教學,我會附在下面。

des=paste("D:/smart",i,".html",sep="")  #產生20個網頁的路徑和檔名。
download.file(loc,des)            #for每次會下載網頁從i=1~i=20
Sys.sleep(runif(1,2,5))           
# 若下載太多頁需要讓每次迴圈休息幾秒,不然網站會偵測到你讓伺服器負荷太大不讓你下載網頁。
}
爬取下載後的20個網頁文章討論標題,使用for迴圈及paste函數就可以爬取20頁的討論文章標題了。
smarttitle=NULL
for(i in 1:20){
  pathfile=paste("D:/smart",i,".html",sep="")  #產生讀取網頁檔案的路徑
  mtitle=read_html(pathfile) %>%                  
html_nodes(".topic_gen") %>%                   #用Selector選擇抓標題後得到的程式碼
  html_text() %>%  iconv("UTF-8")               #抓文字
smarttitle=c(smarttitle,mtitle)        #將每次for迴圈產的一頁的標題儲存到smarttitile
}
smarttitle =data.frame(smarttitle)    #儲存成表格
來看爬的結果,每頁有30篇討論,所以總共爬下600個文章標題囉!
當然還有更進階的爬蟲,附在後面的連結。

3.想爬mobile01標題上面有個浮標顯示人氣,沒辦法直接用Selector選擇,要怎麼做呢?




這時需要按ctrl+u去看網頁原始碼,接著ctrl+f搜尋127811找到這段程式碼。
可以看到第一行的接近尾端位置有href,後面括弧是這文章的網址,接著往下行看到我們要的人氣寫在title後面,其實這幾個就是html的網頁屬性啦,所以這跟上篇提到的抓網址方法幾乎是一樣的,所以你只要把本來的html_attr("href")改成html_("title")就可以抓到人氣囉!
read_html("D:/smart1.html") %>%
 html_nodes(".topic_gen") %>%html_attr("title")

[1] "人氣: 22"     "人氣: 671"    "人氣: 473"    "人氣: 330"    "人氣: 913"    "人氣: 451"   
 [7] "人氣: 462"    "人氣: 352"    "人氣: 550"    "人氣: 429"    "人氣: 1331"   "人氣: 748"   
[13] "人氣: 1100"   "人氣: 253"    "人氣: 649"    "人氣: 127690" "人氣: 1122"   "人氣: 572"   
[19] "人氣: 704"    "人氣: 1111"   "人氣: 7249"   "人氣: 4400"   "人氣: 781"    "人氣: 2596"  
[25] "人氣: 1551"   "人氣: 880"    "人氣: 1738"   "人氣: 1727"   "人氣: 3696"   "人氣: 330" 
抓到人氣後,可以使用substr()函數把數字的部分挑出來。
x="人氣: 1551"
substr(x,5,nchar(x))   
#第2個參數輸入想要的字串開始位置,第3個輸入想要字串結束的位置,
#使用nchar(x)計算字串長度,所以是都會挑到最後一個

[1] "1551"     #結果
--------------------------------------------------------------------------------------------------------------------------

 若不太了解rvest套件怎麼用,可以先參考
超簡單爬蟲教學-使用R軟體的rvest套件抓網站資料(基礎篇)


 爬到想要的資訊之後再整理一下,就可以做很多分析,其中一個是做文字探勘,有別人做的教學也附在下面連結。

若有問題或建議,歡迎留言交流喔!!




參考資料:

進階的使用rvest爬Indeed職缺內容(英文)
http://stat4701.github.io/edav/2015/04/02/rvest_tutorial/


R字串相關函數教學
https://www.ptt.cc/bbs/Statistics/M.1277714037.A.2CC.html
http://molecular-service-science.com/2015/01/18/text-processing-in-r-using-grep/

文字探勘相關教學
http://rstudio-pubs-static.s3.amazonaws.com/12422_b2b48bb2da7942acaca5ace45bd8c60c.html
http://www.slideshare.net/tw_dsconf/r-64232974
https://cran.r-project.org/web/packages/text2vec/vignettes/text-vectorization.html