• 健壮爬虫异常超时问题


    目录:

    • 一:基础try&except异常处理
    • 二:普通请求函数的超时处理
    • 三:selenium+chrome  | phantomjs 的超时处理
    • 四:自定义函数的死锁or超时处理
    • 五:自定义线程的死锁or超时处理
    • 六:自重启的程序设计

    一:基础try&except异常处理

    try&except的语句作用不仅仅是要让其捕获异常更重要的是让其忽略异常,因为爬虫中的绝大多数异常可能重新请求就不存在,因此,发现异常的时候将其任务队列进行修复其实是个最省力的好办法。

    其次被try包住的语句即使出错也不会导致整个程序的退出,相信我,你绝对不希望计划跑一个周末的程序在半夜停止了。

     
     
     
     
     
    Python
     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     try:
        passhttp://top.jobbole.com/deliver-article/#
        #可能出错的语句
    except Exception,e:
        pass
        #保留错误的url,留待下次重跑
        print e
    finally:
        #无论是否处理了异常都继续运行
        print time.ctime()

    二:请求函数的超时处理

    2.1:普通请求:

    2.1.1单请求类型:

     
     
     
     
     
    Python
     
    1
    2
    import requests
    requests.get(url,timeout=60)
    2.1.2会话保持类型:
     
     
     
     
     
    Python
     
    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。主要设置语句是

     
     
     
     
     
    JavaScript
     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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)来处理

     
     
     
     
     
    Python
     
    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这个命令先做测试,

     
     
     
     
     
    Python
     
    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()

    六:自重启的程序设计

    比如程序在某种情况下报错多次,,那么满足条件后,让其重启即可解决大多数问题,当然这只不过是治标不治本而已,如果这个程序重启没有大问题(例如读队列类型)那么自重启这是最省力的方式之一。

     
     
     
     
     
    Python
     
    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()
  • 相关阅读:
    安居客scrapy房产信息爬取到数据可视化(下)-可视化代码
    安居客scrapy房产信息爬取到数据可视化(上)-scrapy爬虫
    反贪风暴4-猫眼影评从爬取到可视化
    vue实战:路由监听
    vue实战——登录页面
    一个电商首页
    网页换肤
    小游戏—九宫格(拼图游戏)
    复选框(checkbox)、多选框
    CSS实现水平垂直居中
  • 原文地址:https://www.cnblogs.com/pyxiaomangshe/p/8206091.html
Copyright © 2020-2023  润新知