社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

左手用R右手Python系列——循环中的错误异常规避

R语言中文社区 • 7 年前 • 632 次点击  

杜雨,EasyCharts团队成员,R语言中文社区专栏作者,兴趣方向为:Excel商务图表,R语言数据可视化,地理信息数据可视化。个人公众号:数据小魔方(微信ID:datamofang) ,“数据小魔方”创始人。


上一讲讲了R语言与Pyhton中的异常捕获与错误处理基本知识,今天以一个小案例来进行实战演练,让你的程序遇水搭桥,畅通无阻。

本案例目标网址,今日头条的头条指数行业报告,全都是pdf格式的,需要先抓包获取PDF文件地址,之后我会随机抽取其中5个地址(因为PDF下载要看网速的,特别慢),然后将其中两个地址设置为不存在地址。

这种错误非常常见,当然实际应用中错误类型多种多样,需要你仔细甄别,但解决的基本思路都是这样的。当遇到一个错误地址导致程序遇阻时,使用异常函数先捕获错误异常,然后使用next命令进行绕过即可(Python中的next命令是continue)。

R语言循环中的错误处理:

library("httr") 
library("dplyr") 
library("jsonlite")
url"https://index.toutiao.com/api/report"

构建下载函数:

GETPDFfunction(url){
  myresult        "Host"="index.toutiao.com", 
       "User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"        )  payload "page"=1,"size"=12)
 for (i in 1:16){     payload[["page"]]=i     web % content(as="text",encoding="UTF-8") %>% fromJSON() %>% `[[`(9)       myresult 1))     print(sprintf("正在抓取第 【%d】 页数据",i))  }  print("所有16页报告数据全部抓取完毕!!!")
 return(myresult) }

运行数据抓取函数:

myresult

#按照id排序
myresult

#将数据框中的PDF地址链接补全
myresult$path"https://mlab.toutiao.com/report/download/"
,myresult$path)
#随机抽取其中5个标题和地址
Test1:189,5),c("title","path")]




    
Test[5,2]'//mlab.toutiao.com/report/download/report47.pdf'
#将其中的第3、5个地址设置为越界地址(就是网址合法但是索引越界,那么你请求不到合法数据)
Test[3,2]"https://mlab.toutiao.com/report/download/report570.pdf"
Test[5,2]"https://mlab.toutiao.com/report/download/report470.pdf"

使用越界地址在浏览器中请求的返回界面是这样的!

接下来使用含有两个越界地址的向量进行PDF循环下载:

存在隐患的代码:

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

加入错误捕获的代码(方案1——使用tryCatch):

for(i in 1:nrow(Test)){
tryCatch({   download.file(Test$path[i],paste0(Test$title[i],".pdf"), mode = "wb")   print(sprintf("正在打印第【%d】",i)) },error   = function(e) {   print(sprintf("第【%d】页地址无效,继续下一页!",i)) }) Sys.sleep(runif(1)) }

加入错误捕获的代码(方案1——使用try):

for (i in 1:nrow(Test)){
  Error try(download.file(Test$path[i],paste0(Test$title[i],".pdf"), mode = "wb"))
 if(!'try-error' %in% class(Error)){    download.file(Test$path[i],paste0(Test$title[i],".pdf"), mode = "wb")    print(sprintf("正在打印第【%d】",i))  } else {    print(sprintf("第【%d】页地址无效,继续下一页!",i))
   next  }   Sys.sleep(runif(1)) }

以上两段代码都是合法的代码,输出了3个正确的PDF文档,tryCatch和try都可以用来绕过循环,tryCatch看起来更具有其他语言的通用排错风格,错误捕获之后会直接忽略错误项,跳到下一轮循环,try则是我们通过if判断,指定了错误项的处理方案是next(也就是忽略本次循环,直接跳转到下一个循环)。

但是如果你在不知情的情况下,不做任何异常处理,那么遇到错误链接导致进程阻塞,编辑器会自己弹出错误,然后中断进程,这是我们不愿意看到的。

Python:

import json
import random
import requests
import pandas as pd
import osimport time

仍然时先抓取PDF下载地址:




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


#随机选择5个记录:
Test=mydata.loc[:5,['title','path']]
#拼接成完整的下载链接
Test['path']=['https://mlab.toutiao.com/report/download/'+text for text in Test['path']]
#随机设置两个越界地址
Test['path'][[3,5]]='https://mla.toutiao.com/download/500.pdf'
os.chdir("D:/Python/File")

不设置任务错误捕获机制:

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

设置容错处理后的代码:

for i in range(len(Test)):
   try:        file=requests.get(Test['path'][i]).content
       with open('{}.pdf'.format(Test['title'][i]), 'wb') as f:            f.write(file)        print("第{}个文件已下载完毕!!!".format(i+1))
   except requests.exceptions.ConnectionError as e:        print("第{}个文件下载失败,失败原因:\n".format(i+1),e)
       continue    time.sleep(0.5)

#保存这份数据,或许以后还有用!
mydata.to_csv("D:/Python/File/toutiaoreport.csv")

可以看到,R语言与Python的错误捕获与规避机制都很好理解,只要在合适的位置放置好错误捕获函数,并同时指定出错后的解决错误就可以了,通常在循环中下载二进制文件或者提取数据,使用R语言中的next或者Python中的continue函数可以成功绕过循环中的失败任务,从而保持整个进程一直进行到循环结束,自动退出!

在线课程请点击文末原文链接:
往期案例数据请移步本人GitHub:
https://github.com/ljtyduyu/DataWarehouse/tree/master/File

公众号后台回复关键字即可学习

回复 R               R语言快速入门免费视频 
回复 统计          统计方法及其在R中的实现
回复 用户画像   民生银行客户画像搭建与应用 
回复 大数据      大数据系列免费视频教程
回复 可视化      利用R语言做数据可视化
回复 数据挖掘   数据挖掘算法原理解释与应用
回复 机器学习   R&Python机器学习入门 


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/sNJ10T2OdO
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/4619
 
632 次点击