Tuesday, March 31, 2015php
以前用rvest幫人寫了一個按期抓取amazon價格庫存,並與以前價格比較的小程序,算是近期寫過的第一個完整的程序了。裏面涉及了一些報錯的處理。html
這裏主要參考了stackoverflow上的如下問答:java
tryCatch部分,後續查找資料,發現如下博文: 1. R語言使用tryCatch進行簡單的錯誤處理express
如下是代碼示例:小程序
1)使用tryCatch函數跳過錯誤信息。(示例以download.file爲樣式)less
看如下代碼。這裏須要批量下載一堆amazon產品信息。若是產品ID號不對,或者IP被限制,網頁會打不開,而download.file會報錯。我這裏用tryCatch來獲取網頁打不開時的錯誤信息。而且要求執行下一步循環「」。ide
for (n in 1:length(productlink)){ tryCatch({ download.file(productlink[n],paste0(getwd(),"/html/",productid[n,],".html"),cacheOK = TRUE) },error=function(e){cat("ERROR :",conditionMessage(e),"\n")}) Sys.sleep(0.5) #增長了Sys.sleep(seconds)函數,讓每一步循環都暫停一段時間。這個雖然會下降程序速度,但對於有訪問限制的網站,不失爲一個好的辦法。 }
上述示例由兩個重要函數構成,即tryCatch和cat函數
查閱函數,tryCatch屬於base包,condition system。在R語言使用tryCatch進行簡單的錯誤處理這篇博文裏有tryCatch的簡單示範以下:oop
result = tryCatch( {expr}, warning = function(w) {warning-handler-code}, error = function(e) { error-handler-code}, finally = {cleanup-code} )
即若是warning時,對warning怎麼處理,若是error時對error怎麼處理。若是沒有任何條件吻合,則最後會輸出expr裏的內容。若是有final項的話,則會同時輸出finally項以及expr項佈局
tryCatch({a<-"c" b<-"c" b==a}, error=function(e){cat("hahaha",conditionMessage(e),"\n\n")}, finally={print("ccc")})
[1] "ccc"
[1] TRUE
tryCatch({a<-"c"
cc==a}, #cc不存在 error=function(e){cat("hahaha",conditionMessage(e),"\n\n")}, finally={print("ccc")})
hahaha object 'cc' not found
對於代碼示例,即爲,download成功則返回download內容,不成功則返回error=function(e){cat("ERROR :",conditionMessage(e),"\n")}
而後是cat函數。這個cat是一個輸入輸出值。這裏等於,要求系統輸出「ERROR :」+conditionMessage(e)的內容。而後用「」分行。
另外,在stackoverflow上的這篇問答,由mmann1123回答的問題裏,咱們看到了更爲有趣的一個應用。
這裏收縮起來,展開亦可閱讀。
#!/usr/bin/env Rscript # tryCatch.r -- experiments with tryCatch # Get any arguments arguments <- commandArgs(trailingOnly=TRUE) a <- arguments[1] # Define a division function that can issue warnings and errors myDivide <- function(d, a) { if (a == 'warning') { return_value <- 'myDivide warning result' warning("myDivide warning message") } else if (a == 'error') { return_value <- 'myDivide error result' stop("myDivide error message") } else { return_value = d / as.numeric(a) } return(return_value) } # Evalute the desired series of expressions inside of tryCatch result <- tryCatch({ b <- 2 c <- b^2 d <- c+2 if (a == 'suppress-warnings') { e <- suppressWarnings(myDivide(d,a)) } else { e <- myDivide(d,a) # 6/a } f <- e + 100 }, warning = function(war) { # warning handler picks up where error was generated print(paste("MY_WARNING: ",war)) b <- "changing 'b' inside the warning handler has no effect" e <- myDivide(d,0.1) # =60 f <- e + 100 return(f) }, error = function(err) { # warning handler picks up where error was generated print(paste("MY_ERROR: ",err)) b <- "changing 'b' inside the error handler has no effect" e <- myDivide(d,0.01) # =600 f <- e + 100 return(f) }, finally = { print(paste("a =",a)) print(paste("b =",b)) print(paste("c =",c)) print(paste("d =",d)) # NOTE: Finally is evaluated in the context of of the inital # NOTE: tryCatch block and 'e' will not exist if a warning # NOTE: or error occurred. #print(paste("e =",e)) }) # END tryCatch print(paste("result =",result))
2)利用if語句以及stop語句。
即,若是某條件不成立,則中止程序,並輸出stop裏的內容。我這裏主要用於檢查原始product id是否輸入正確。
if (!sum(check)==length(productlink)) { productlink<-NULL productid<-NULL stop("invalid productid please double check if any space or else in, and resave the file or the script will not run") }
3)處理使用data.frame批量讀取數據時,元素由於不存在致使的data.frame報錯。
譬如說如下示例,由於a不存在,而致使data.frame報錯。
a<-NULL b<-c("cc","dd") data.frame(a,d) > Error in data.frame(a, d) : 參數值意味着不一樣的行數: 0, 2
所以,對於在循環裏,須要先單獨合成data.frame,再使用rbind把各個data.frame合成在一塊兒時,能夠考慮增長異常值的賦值。以下面兩段,若是我拉的網頁裏不存在product name,則length(productname)==1爲FALSE,直接輸出「product not download or not existing」,那麼這個字段就不是空值或者2-3個行,而是1行,以後合併爲data.frame時就不會報錯了。
data<-function(n){ ####隱掉得到productname/price/category的代碼 if(!length(productname)==1) {productname="Product not download or not existing"} if (!length(price)==1) { price=NA category<-"Product not download or not existing" } data.frame(productname,price,category) #這裏合成data.frame,若是這三個行數不等(多爲空值NULL,或者某個字段有2-3行所致使。 #使用上面的IF判斷賦值的好處是,最後出來的productname,price,category保證是1行,能夠用data.frame合併。而且對異常值也有輸出。
因爲處理第2/3類錯誤時我還不瞭解tryCatch函數。目前看下來,貌似tryCatch函數能作的事情更多?
寫下來供之後寫代碼時參考。
另外,tryCatch在java,C裏均有相似功效。看來R歸根到底,仍是脫離不了底層語言啊。
接下來4月的學習計劃,學完一個就寫一篇博文~~整理思路記錄筆記。
1)rCurl包,以及它那個厚厚的英文說明書。但願最後能學會用它爬一些rvest沒法爬的腳本網頁,以及搜索框網頁等
2)用R作金融時間序列分析(煉數成金的班)
3)跟着肖星老師從新複習財務分析知識(mooc課),在複習過去的財務知識後,再從新來看預測者網下的股票數據,嘗試作一下挖掘與分析,至少從宏觀上了解當前中國上市公司的佈局與特色,爲之後用R研究股票打打基礎。
----------
個人博客: http://www.cnblogs.com/weibaar 記錄學習R與數據分析的一切。