2014年5月6日 星期二

[R]用R抓網頁資料

        幾個月以前老闆丟了個問題"氣象跟業績會不會有關係啊?",老闆請人當然就是為了解決問題,所以當下我馬上點頭如搗蒜答應了(殊不知才是痛苦的開始)。我當下想法很簡單,中央氣象局有OPEN DATA,從上面抓氣象資料就可以了。但是事實總比想像殘酷。第一,中央氣象局的OPEN DATA格式是XML格式,當時的我只會處理傳統結構化資料,對於網頁資料完全沒轍。第二,中央氣象局提供的氣溫資料只有月份資料!!!太粗糙啦!!根本不符合需求。所以當時就以沒有資料為藉口推掉了這個工作。


        但是人總是范建,最近開始玩R之後,認識了一些網路抓取的套件,就想說可以來試試看。剛好也找到一個強國的氣象網(http://lishi.tianqi.com/),涵蓋強國各地近三年每天的的氣候資料,強國的氣象網不知道為什麼剛好包含了鄰國台灣資料(聽說強國網站是遮蔽GOOGLE,應該不容易查到我),所以就以強國的網站為資料來源來牛刀小試一番。廢話不多說直接看原始碼:
library(XML)
library(RCurl)
##generate the list of url
#產生空白的list存放欲抓網站的URL
url_list <- list()
#觀察原始網站如"http://lishi.tianqi.com/taibei/201101.html"
#月份'01'、'02'是字串格式,預先製作一個陣列存放
month <- c('01','02','03','04','05','06','07', '08', '09', '10', '11', '12')
#利用迴圈自動產生月份網址
for (year in 2011:2013){
url <- paste('http://lishi.tianqi.com/taibei/',year,month,'.html',sep='')
url_list <- rbind(url_list,url)
}
#將產生的網址去格式化,方便讀取
url_list <- unlist(url_list)
##Get the table online
#核心程式
myTemp <- function(url){
#抓取url
get_url = getURL(url,encoding = "UTF-8")
#將url解析
get_url_parse = htmlParse(get_url, encoding = "UTF-8")
#抓取關鍵的變項,我們需要的變項夾在一個div的class=tqtongji2,裡面<ul>中的<li>標籤裡面
#標籤裡面還有一些沒有用到的東西沒關係,事後再一併移除
tablehead <- xpathSApply(get_url_parse, "//div[@class='tqtongji2']/ul/li", xmlValue)
#將擷取到的關鍵字轉成容易閱讀的矩陣格式
table <- matrix(tablehead, ncol = 6, byrow = T)
#回傳值
return(table)
}
#lapply是個好用的指令,在SAS要做類似的事情都會使用MACRO變項
#但是R是向量語言,把要跑的變項放在一個向量(url_list) ,把公式放在第二個參數位置
#R會自動為第一個向量中的每個元素代入到公式之中
#產生出的的Temp_Total是個list,存放每一次的結果
Temp_Total <- lapply(url_list, myTemp)
##Transform the data from list to matrix
##將結果的LIST轉成矩陣方便分析
#建立一個有六個欄位的矩陣
Temp <- matrix(ncol = 6)
#分別取出list中的每個元素,貼到矩陣裡面
for (i in 1:36){
tmp <- Temp_Total[[i]]
Temp <- rbind(test,tmp)
}
write.csv(Temp,file = "Temp.csv" ,sep = ",", row.names = F)
view raw gistfile1.txt hosted with ❤ by GitHub

發文不附圖不可取,附上結果,亂碼是因為強國字博大精深看不懂:



7 則留言:

  1. 還不錯用,但是要玩得專業的話,還是要用PYTHON之類的真正的程式語言寫爬蟲
    R只能簡單撐撐場

    回覆刪除
  2. 强国= =
    难道台湾同胞这么称呼大陆么= =

    回覆刪除
  3. 强国= =
    难道台湾同胞这么称呼大陆么= =

    回覆刪除
  4. 您好,最後一段 Temp <- rbind(test,tmp) 出現Error in rbind(test, tmp) : object 'test' not found,請問您有這個問題嗎

    回覆刪除
    回覆
    1. 抱歉因為時間久遠找不到原始檔,test當初應該就是一個測試資料集,沒有放在程式碼裡面

      刪除