python爬虫实战之抓取异常如何处理?

最近教大家用爬虫采集数据比较频繁,有些小伙伴在使用的时候难免出错,跟小编进行了交流之后也都成功解决了出错点。这里把大家容易出错的两种情况整理了出来,没有出错的小伙伴也可以一起看看,在查错的途中回顾与运用我们所学的知识点。下面就python爬虫抓取异常处理办法进行讲解。

可能在抓取的时候,某个账号突然就被封了,或者由于网络原因,某次请求失败了,该如何处理?对于前者,我们需要判断每次请求返回的内容是否符合预期,也就是看response url是否正常,看response content是否是404或者让你验证手机号等,对于后者,我们可以做一个简单的重试策略。处理这两种情况的代码如下

@timeout_decorator

def get_page(url, user_verify=True, need_login=True):

    """

    :param url: 待抓取url

    :param user_verify: 是否为可能出现验证码的页面(ajax连接不会出现验证码,如果是请求微博或者用户信息可能出现验证码),否为抓取转发的ajax连接

    :param need_login: 抓取页面是否需要登录,这样做可以减小一些账号的压力

    :return: 返回请求的数据,如果出现404或者403,或者是别的异常,都返回空字符串

    """

    crawler.info('本次抓取的url为{url}'.format(url=url))

    count = 0

  

    while count < max_retries:

  

        if need_login:

            # 每次重试的时候都换cookies,并且和上次不同,如果只有一个账号,那么就允许相同

            name_cookies = Cookies.fetch_cookies()

             

            if name_cookies is None:

                crawler.warning('cookie池中不存在cookie,正在检查是否有可用账号')

                rs = get_login_info()

  

                # 选择状态正常的账号进行登录,账号都不可用就停掉celery worker

                if len(rs) == 0:

                    crawler.error('账号均不可用,请检查账号健康状况')

                    # 杀死所有关于celery的进程

                    if 'win32' in sys.platform:

                        os.popen('taskkill /F /IM "celery*"')

                    else:

                        os.popen('pkill -f "celery"')

                else:

                    crawler.info('重新获取cookie中...')

                    login.excute_login_task()

                    time.sleep(10)

  

        try:

            if need_login:

                resp = requests.get(url, headers=headers, cookies=name_cookies[1], timeout=time_out, verify=False)

  

                if "$CONFIG['islogin'] = '0'" in resp.text:

                    crawler.warning('账号{}出现异常'.format(name_cookies[0]))

                    freeze_account(name_cookies[0], 0)

                    Cookies.delete_cookies(name_cookies[0])

                    continue

            else:

                resp = requests.get(url, headers=headers, timeout=time_out, verify=False)

  

            page = resp.text

            if page:

                page = page.encode('utf-8', 'ignore').decode('utf-8')

            else:

                continue

  

            # 每次抓取过后程序sleep的时间,降低封号危险

            time.sleep(interal)

  

            if user_verify:

                if 'unfreeze' in resp.url or 'accessdeny' in resp.url or 'userblock' in resp.url or is_403(page):

                    crawler.warning('账号{}已经被冻结'.format(name_cookies[0]))

                    freeze_account(name_cookies[0], 0)

                    Cookies.delete_cookies(name_cookies[0])

                    count += 1

                    continue

  

                if 'verifybmobile' in resp.url:

                    crawler.warning('账号{}功能被锁定,需要手机解锁'.format(name_cookies[0]))

         

                    freeze_account(name_cookies[0], -1)

                    Cookies.delete_cookies(name_cookies[0])

                    continue

  

                if not is_complete(page):

                    count += 1

                    continue

  

                if is_404(page):

                    crawler.warning('url为{url}的连接不存在'.format(url=url))

                    return ''

  

        except (requests.exceptions.ReadTimeout, requests.exceptions.ConnectionError, AttributeError) as e:

            crawler.warning('抓取{}出现异常,具体信息是{}'.format(url, e))

            count += 1

            time.sleep(excp_interal)

  

        else:

            Urls.store_crawl_url(url, 1)

            return page

  

    crawler.warning('抓取{}已达到最大重试次数,请在redis的失败队列中查看该url并检查原因'.format(url))

    Urls.store_crawl_url(url, 0)

return ''

 

这里大家把上述代码当一段伪代码读就行了,主要看看如何处理抓取时候的异常。因为如果贴整个用户抓取的代码,不是很现实,代码量有点大。

有同样抓取出错的小伙伴需要好好研究本篇文章,然后看自己是哪一种出错的类型再进行解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值