Python爬虫框架之异常处理
任何访问服务器获取数据的请求,都需要做异常处理,当然爬虫更需要我们对各种异常进行处理。只有这样才能提高爬虫的健壮性。如果我们的爬虫足够健壮,那么就能确保程序几个月不停止。
我们从以下几个方面做出讲解:
- 一:try except处理异常代码块
- 二:普通请求函数的超时处理
- 三:selenium+chrome | phantomjs 的超时处理
- 四:自定义函数的死锁or超时处理
- 五:自定义线程的死锁or超时处理
- 六:自重启的程序设计
一:基础try except异常处理
try except的语句可以让我们的程序跳过代码中可能出现的异常
1 2 3 4 5 6 7 8 9 10 |
try: pass http://code.py40.com/deliver-article/# #可能出错的语句 except Exception as e: pass #保留错误的url,留待下次重跑 print(e) finally: #无论是否处理了异常都继续运行 print(time.ctime()) |
二:请求函数的超时处理
2.1:普通请求:
2.1.1单请求类型:
1 2 |
import requests requests.get(url,timeout=60) |
2.1.2会话保持类型:
1 2 3 |
import requesocks session = requesocks.session() response = session.get(URL,headers=headers,timeout=10) |
三:selenium+chrome | phantomjs 的超时处理
2.2.1:selenium+chrome的超时设置
官网原文:http://selenium-python.readthedocs.io/waits.html
显式等待:、等待某个条件发生,然后再继续进行代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Firefox() driver.get("http://somedomain/url_that_delays_loading") try: element = WebDriverWait(driver, 10).until( #这里修改时间 EC.presence_of_element_located((By.ID, "myDynamicElement")) ) finally: driver.quit() |
隐式等待:是告诉WebDriver在尝试查找一个或多个元素(如果它们不是立即可用的)时轮询DOM一定时间。默认设置为0,一旦设置,将为WebDriver对象实例的生命期设置隐式等待。
1 2 3 4 5 6 |
from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(10) # seconds driver.get("http://somedomain/url_that_delays_loading") myDynamicElement = driver.find_element_by_id("myDynamicElement") |
2.2.2:phantomjs的超时设置
这里使用不带selenium的phantomjs,需要使用js。主要设置语句是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#JavaScript page.settings.resourceTimeout = 5000; // 等待5秒 var system = require('system'); var args = system.args; var url = args[1]; var page = require('webpage').create(); page.settings.resourceTimeout = 5000; // 等待5秒 page.onResourceTimeout = function(e) { console.log(e.errorCode); //打印错误码 console.log(e.errorString);//打印错误语句 console.log(e.url); //打印错误url phantom.exit(1); }; page.open(url, function(status) { if(status==='success'){ var html=page.evaluate(function(){ returndocument.documentElement.outerHTML; }); console.log(html); } phantom.exit(); }); //$phantomjs xx.js http://bbs.pcbaby.com.cn/topic-2149414.html |
四:自定义函数的死锁or超时处理
这个非常重要!!
python是顺序执行的,但是如果下一句话可能导致死锁(比如一个while(1))那么如何强制让他超时呢?他本身如果没有带有超时设置的话,就要自己运行信号(import signal)来处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#coding:utf-8 import time import signal def test(i): time.sleep(0.999)#模拟超时的情况 print "%d within time"%(i) return i def fuc_time(time_out): # 此为函数超时控制,替换下面的test函数为可能出现未知错误死锁的函数 def handler(signum, frame): raise AssertionError try: signal.signal(signal.SIGALRM, handler) signal.alarm(time_out)#time_out为超时时间 temp = test(1) #函数设置部分,如果未超时则正常返回数据, return temp except AssertionError: print("%d timeout"%(i))# 超时则报错 if __name__ == '__main__': for i in range(1,10): fuc_time(1) |
五:自定义线程的死锁or超时处理
在某个程序中一方面不适合使用selenium+phantomjs的方式(要实现的功能比较难不适合)因为只能用原生的phantomjs,但是这个问题他本身在极端情况下也有可能停止(在超时设置之前因为某些错误)
那么最佳方案就是用python单独开一个线程(进程)调用原生phantomjs,然后对这个线程进程进行超时控制。
这里用ping这个命令先做测试,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import subprocess from threading import Timer import time kill = lambda process: process.kill() cmd = ["ping", "www.google.com"] ping = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) my_timer = Timer(5, kill, [ping])#这里设定时间,和命令 try: my_timer.start()#启用 stdout, stderr = ping.communicate()#获得输出 #print stderr print(time.ctime()) finally: print(time.ctime()) my_timer.cancel() |
六:程序自动重启
比如我们的程序在某种情况下报错多次,那么当满足条件后,让其重启即可解决大多数问题,当然这只不过是治标不治本而已,如果这个程序重启没有大问题(例如读队列类型)那么自重启这是最省力的方式之一。
1 2 3 4 5 6 7 8 9 10 11 12 |
import time import sys import os def restart_program(): python = sys.executable os.execl(python, python, * sys.argv) if __name__ == "__main__": print 'start...' print u"3秒后,程序将结束...".encode("utf8") time.sleep(3) restart_program() |
未经允许不得转载:Python在线学习 » Python爬虫提高之异常处理