左手用R右手Python系列——循環中的錯誤異常規避

上一講講了R語言與Pyhton中的異常捕獲與錯誤處理基本知識,今天以一個小案例來進行實戰演練,讓你的程序遇水搭橋,暢通無阻。

本案例目標網址,今日頭條的頭條指數行業報告,全都是pdf格式的,需要先抓包獲取PDF文件地址,之後我會隨機抽取其中5個地址(因為PDF下載要看網速的,特別慢),然後將其中兩個地址設置為不存在地址。

這種錯誤非常常見,當然實際應用中錯誤類型多種多樣,需要你仔細甄別,但解決的基本思路都是這樣的。當遇到一個錯誤地址導致程序遇阻時,使用異常函數先捕獲錯誤異常,然後使用next命令進行繞過即可(Python中的next命令是continue)。

R語言循環中的錯誤處理:

library("httr") nlibrary("dplyr") nlibrary("jsonlite")nurl<-"https://index.toutiao.com/api/report"n

構建下載函數:

GETPDF<-function(url){n myresult<-data.frame()n headers<-c( n "Host"="index.toutiao.com", n "User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"n )n payload <-list("page"=1,"size"=12)n for (i in 1:16){n payload[["page"]]=in web <- GET(url,add_headers(.headers = headers),query = payload,verbose())n content <- web %>% content(as="text",encoding="UTF-8") %>% fromJSON() %>% `[[`(9) n myresult <- rbind(myresult,content)n Sys.sleep(runif(1))n print(sprintf("正在抓取第 【%d】 頁數據",i))n }n print("所有16頁報告數據全部抓取完畢!!!")n return(myresult)n}n

運行數據抓取函數:

myresult<-GETPDF(url)n

#按照id排序nmyresult<-arrange(myresult,id)n

#將數據框中的PDF地址鏈接補全nmyresult$path<-paste0("https://mlab.toutiao.com/report/download/",myresult$path)n#隨機抽取其中5個標題和地址nTest<-myresult[sample(1:189,5),c("title","path")]n

Test[5,2]//mlab.toutiao.com/report/download/report47.pdfn#將其中的第3、5個地址設置為越界地址(就是網址合法但是索引越界,那麼你請求不到合法數據)nTest[3,2]<-"https://mlab.toutiao.com/report/download/report570.pdf"nTest[5,2]<-"https://mlab.toutiao.com/report/download/report470.pdf"n

使用越界地址在瀏覽器中請求的返回界面是這樣的!

接下來使用含有兩個越界地址的向量進行PDF循環下載:

存在隱患的代碼:

setwd("D:/R")nfor(i in 1:nrow(Test)){n download.file(Test$path[i],paste0(Test$title[i],".pdf"), mode = "wb")n print(sprintf("正在列印第%d",i))n Sys.sleep(runif(1))n}n

加入錯誤捕獲的代碼(方案1——使用tryCatch):

for(i in 1:nrow(Test)){ntryCatch({n download.file(Test$path[i],paste0(Test$title[i],".pdf"), mode = "wb")n print(sprintf("正在列印第【%d】",i)) n },error = function(e) { n print(sprintf("第【%d】頁地址無效,繼續下一頁!",i))n })n Sys.sleep(runif(1))n}n

加入錯誤捕獲的代碼(方案1——使用try):

for (i in 1:nrow(Test)){n Error <- try(download.file(Test$path[i],paste0(Test$title[i],".pdf"), mode = "wb"))n if(!try-error %in% class(Error)){n download.file(Test$path[i],paste0(Test$title[i],".pdf"), mode = "wb")n print(sprintf("正在列印第【%d】",i))n } else {n print(sprintf("第【%d】頁地址無效,繼續下一頁!",i))n nextn }n Sys.sleep(runif(1))n}n

以上兩段代碼都是合法的代碼,輸出了3個正確的PDF文檔,tryCatch和try都可以用來繞過循環,tryCatch看起來更具有其他語言的通用排錯風格,錯誤捕獲之後會直接忽略錯誤項,跳到下一輪循環,try則是我們通過if判斷,指定了錯誤項的處理方案是next(也就是忽略本次循環,直接跳轉到下一個循環)。

但是如果你在不知情的情況下,不做任何異常處理,那麼遇到錯誤鏈接導致進程阻塞,編輯器會自己彈出錯誤,然後中斷進程,這是我們不願意看到的。

Python:

import jsonnimport randomnimport requestsnimport pandas as pdnimport osimport timen

仍然時先抓取PDF下載地址:

headers={n "Host":"index.toutiao.com",n "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"n }npayload ={"page":1,"size":12}nurl="https://index.toutiao.com/api/report"ndef GETPDF(url,headers=headers,payload=payload):n fullinfo=[]n for i in range(1,17):n payload[pageIndex]=in r=requests.get(url,params=payload,headers=headers)n content=r.json()n fullinfo=fullinfo+content[data]n print("第{}部分已載入".format(i))n print("所有頁面均以載入完!!!")n return fullinfonmydata=GETPDF(url)nmydata=pd.DataFrame(mydata)n

#隨機選擇5個記錄:nTest=mydata.loc[:5,[title,path]]n#拼接成完整的下載鏈接nTest[path]=[https://mlab.toutiao.com/report/download/+text for text in Test[path]]n#隨機設置兩個越界地址nTest[path][[3,5]]=https://mla.toutiao.com/download/500.pdfnos.chdir("D:/Python/File")n

不設置任務錯誤捕獲機制:

for i in range(len(Test)):n file=requests.get(Test[path][i]).contentn with open({}.pdf.format(Test[title][i]), wb) as f:n f.write(file)n print("第{}個文件已下載完畢!!!".format(i))n time.sleep(1)n

設置容錯處理後的代碼:

for i in range(len(Test)):n try:n file=requests.get(Test[path][i]).contentn with open({}.pdf.format(Test[title][i]), wb) as f:n f.write(file)n print("第{}個文件已下載完畢!!!".format(i+1))n except requests.exceptions.ConnectionError as e:n print("第{}個文件下載失敗,失敗原因:n".format(i+1),e)n continuen time.sleep(0.5)n

#保存這份數據,或許以後還有用!nmydata.to_csv("D:/Python/File/toutiaoreport.csv")n

可以看到,R語言與Python的錯誤捕獲與規避機制都很好理解,只要在合適的位置放置好錯誤捕獲函數,並同時指定出錯後的解決錯誤就可以了,通常在循環中下載二進位文件或者提取數據,使用R語言中的next或者Python中的continue函數可以成功繞過循環中的失敗任務,從而保持整個進程一直進行到循環結束,自動退出!

在線課程請點擊文末原文鏈接:

Hellobi Live | 9月12日 R語言可視化在商務場景中的應用

往期案例數據請移步本人GitHub:

github.com/ljtyduyu/Dat


推薦閱讀:

TAG:市場營銷 | 大學 | 大學教育 | 市場營銷專業 | 國際貿易 | 共和黨美國 | 中美關係? | 唐納德·約翰·特朗普DonaldJTrump | 特朗普政府及其內閣 | 台灣 | 兩岸關係與發展 | 台灣問題 | 论语书籍 | 印度 | 投资 | 故事 | 小米手机 | 小米科技 | iPhoneX | 燃料电池Fuelcell | 比特幣Bitcoin | 紫薯 | 烘焙 | 减肥 | 王路的粽子铺 | 心理學 | 人際交往 | 溝通 | 家庭關係 | 父母 | 章子怡演员 | 无问西东电影 | 今日头条应用 | 社会心理学 | 群体心理 | 行为决策学 | 汽车 | 新手开车 | 增长黑客 | 产品运营 | 手机社交软件 | 语言学习 | 健身 | 減肥 | 肌肉 | 脂肪 | 肌肉訓練 | 书法 | 毛笔书法 | 艺术 | HEROSONE | AnimeTamashii | wwwanitamacn | 心理学 | 人际交往 | 生活方式 | R编程语言 | Python | 数据分析 |