小爬虫项目遇到的bug

这篇具有很好参考价值的文章主要介绍了小爬虫项目遇到的bug。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

小爬虫项目遇到的bug

项目背景是这样的, 三个请求数据的接口,是标准的 JWT 认证,提前五分钟刷新token,这个操作是在每次请求数据之前都会进行的检查。
业务场景是这样的: 每个账号都需要请求三个接口,为了简单就做成了定时任务的模式,所以每个账号下就会有三个任务,每次刷新完token,都会将token存入到数据库,以便于下次能重新拿到最新的token。
遇到的问题: 在某次查看日志的时候,发现每次刷新完token之后就会掉线。

伪代码

# -*- coding:utf-8  -*-
# @Time     : 2021-02-21 02:32
# @Author   : BGLB
# @Software : PyCharm


class Spider():

    def task_1():
        if not self.refresh_token():
            return False
            print('task_1....', self.token))
            time.sleep(5)

    def task_2():
        if not self.refresh_token():
            return False
        print('task_2...', self.token))
        time.sleep(5)

    def task_3():
        if not self.refresh_token():
            return False
        print('task_3....', self.token))
        time.sleep(5)

    def refresh_token(self, force: bool = False) -> bool:
        """
        force: 强制刷新token
        :return:
         bool
        """
        self.token = ''
        return True


def main():
    spider = Spider()
    task_1_thread = Thread(target=spider.task_1, )
    task_2_thread = Thread(target=spider.task_2, )
    task_3_thread = Thread(target=spider.task_3, )

    task_1_thread.start()
    task_2_thread.start()
    task_3_thread.start()
    while True:
        time.sleep(10)

if __name__ == '__main__':
    main()
    

找出背锅侠

定时任务 由于我们的每次启动任务的时候几乎每个账号的每个任务是同时启动的,在 task_1 任务中刷新token之后,新的token还没有保存到数据库,task_2task_3 任务拿到的还是旧的token 所以还是需要去刷新token,这一刷新不就出大问题了。当然任务这块不是我写的,但是问题要解决啊,怀着对他人代码的敬畏之心,我毅然决然的一头扎入自己的代码之中…

解决之道

  1. 找 chatgpt 寻一个分布式锁
  2. 在每次刷新 token 前获取一个锁,如果没有拿到锁,就循环从redis中获取新的token, 删除这个新的token
  3. 每次刷新完之后把最新的token放入到redis中以便于其他任务获取。

最终修改后的代码如下

# -*- coding:utf-8  -*-
# @Time     : 2023/6/8 0:25
# @Author   : BGLB
# @Software : PyCharm
import time
import uuid
from threading import Thread


def acquire_lock(redis_client, lock_name, acquire_time=10, time_out=10):
    """获取一个分布式锁"""
    identifier = str(uuid.uuid4())
    end = time.time()+acquire_time
    lock = "string:lock:"+lock_name
    while time.time() < end:
        if redis_client.setnx(lock, identifier):
            # 给锁设置超时时间, 防止进程崩溃导致其他进程无法获取锁
            redis_client.expire(lock, time_out)
            return identifier
        elif not redis_client.ttl(lock):
            redis_client.expire(lock, time_out)
        time.sleep(0.001)
    return False


def release_lock(redis_client, lock_name, identifier):
    """通用的锁释放函数"""
    lock = "string:lock:"+lock_name
    pip = redis_client.pipeline(True)
    while True:
        try:
            pip.watch(lock)
            lock_value = redis_client.get(lock)
            if not lock_value:
                return True

            if lock_value.decode() == identifier:
                pip.multi()
                pip.delete(lock)
                pip.execute()
                return True
            pip.unwatch()
            break
        except Exception:
            pass
    return False


def redis_client():
    pool = redis.ConnectionPool(**REDIS_CONFIG, decode_responses=True)
    r = redis.Redis(connection_pool=pool)
    return r


class Spider():

    def __init__(self, account):
        self.account = account
        self.token = ''
        self._redis_client = None

    def task_1(self):
        if not self.refresh_token():
            return False
        print('task_1....', self.token))
        time.sleep(5)

    def task_2(self):
        if not self.refresh_token():
            return False
        print('task_2...', self.token))
        time.sleep(5)

    def task_3(self):
        if not self.refresh_token():
            return False
        print('task_3....', self.token)
        time.sleep(5)

    def refresh_token(self, force: bool = False) -> bool:
        """
        force: 强制刷新token
        :return:
         bool
        """
        new_token = ''
        lock_key = f'refreshing_token_{self.account}'
        token_key = f'new_token_{self.account}'
        lock = acquire_lock(self.redis_client, lock_key, acquire_time=2)
        if not lock:
            # 从缓存中获取新的token
            time_start = time.time()
            while time.time() - time_start < 5:
                new_token = self.redis_client.get(token_key)
                print('wait other task refreshing token')
                if new_token:
                    self.redis_client.delete(token_key)
                    break
                time.sleep(0.5)
        else:
            # 请求刷新token 的接口
            try:
                new_token = ''
            except Exception as e:
                raise e
            finally:
                release_lock(self.redis_client, lock_key, lock)

        self.token = new_token
        print('refresh_token finish')
        return True

    @property
    def redis_client(self):
        if not self._redis_client:
            self._redis_client = redis_client()
        return self._redis_client


def main():
    spider = Spider(account='123456')
    task_1_thread = Thread(target=spider.task_1, )
    task_2_thread = Thread(target=spider.task_2, )
    task_3_thread = Thread(target=spider.task_3, )

    task_1_thread.start()
    task_2_thread.start()
    task_3_thread.start()
    while True:
        time.sleep(10)


if __name__ == '__main__':
    main()

存疑

刚才在编写伪代码的过程中,我又发现一个问题,如果 task_1 在刷新token, task_1task_2 都在等待中 , task_2 从reids中获取到了新的token,然后就会从redis删除这个token,这个时候呢, task_3会不会就拿不到刷新后的token了?万一这个 task_3 又比较重要,它的返回值决定了所有任务生死,那这个问题是不是就很严重了?
哎,说实话(听我给你编)这原本不是我代码的问题。这是调用的问题,是吧?原本这些检查不是我来处理的,是调用方去处理,每个模块有每个模块的功能啊 是不?还是把调用的代码改一下吧!文章来源地址https://www.toymoban.com/news/detail-482789.html

到了这里,关于小爬虫项目遇到的bug的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何更换电脑背景图片?这样做很简单!

    【我的电脑背景图片是系统自带的壁纸,不太好看,我想把它换成自己的照片。有没有小伙伴知道电脑怎么更换背景图片?在线求个简单的方法!】 在日常生活中,我们常常需要更换电脑背景图片来增强视觉体验或者个性化电脑界面。那么,如何更换 电脑背景图片 呢?如何

    2023年04月19日
    浏览(32)
  • QT遇到资源文件不显示的问题这样解决

    在本例中需要利用画家画出资源图片 第一次没有顺利画出,有以下几点原因 1、注意后缀名格式 本例中如果使用了3.7PNG,在描绘的时候如果用如下代码是无法显示图片的,注意大小写  painter.drawPixmap(20,100,QPixmap(\\\"://捕获/1.png\\\")); .png和.PNG是不同的。 2、注意/和的区别 最简单的

    2024年02月11日
    浏览(33)
  • 【爬虫系统设计系列】好的爬虫系统一定要这样去设计告警功能

    【作者主页】: 吴秋霖 【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作! 【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建

    2024年02月05日
    浏览(27)
  • 遇到无法复现的 Bug

    当我们在软件开发过程中遇到无法复现的 Bug 时,这可能会让我们感到头疼和困惑。处理这种 Bug 需要一些技巧和方法来帮助我们更好地解决问题。本篇博客将为大家总结一些常用的技术手段和策略,希望能对开发者们在日常工作中遇到类似问题时提供一些帮助。 在软件开发

    2024年02月13日
    浏览(31)
  • 【bug】使用mmsegmentaion遇到的问题

    使用的环境是cuda11.3+pytorch1.11.0+torchaudio0.11+torchvison0.12.0 由于之前用自己数据集跑过internImage,想投机取巧把internImage自定义的配置文件拿过来直接用,果不其然报错了。 还是借鉴mmsegmentaion中/configs/ base /datasets/ade20k.py,将文件修改成适合自己数据集的配置 训练是正常的,但是

    2024年04月25日
    浏览(21)
  • idea编译时遇到的bug

    问题描述: D:workspacesparksrcmainScalaWordCount.scala:3:8 WordCount is already defined as object WordCount object WordCount { 解决办法 参考博客:Error:(21, 8) FlumePushWordCount is already defined as object FlumePushWordCount object FlumePushWor_WSQ(E)的博客-CSDN博客 问题描述: Error running \\\'wcPerson\\\': Command line is too long

    2024年02月13日
    浏览(24)
  • 【Vue】路由学习中遇到的BUG

    最近路由学习中遇到了各式各样的飚红,记录下来供大家参考( 其实是怕下次再错X^X 无法读取 undefined 的属性 routes配置中不是components而是component ( 自动提示害人不浅 将components改为component \\\'XXXXX\\\' 未被定义 组件中的name写成变量形式,而变量不存在 将name中所写变量形式改为字

    2024年01月19日
    浏览(55)
  • 前端开发中遇到的小bug--解决方案

    1.在 searchBox 搜索栏中,用到了多级下拉框的筛选条件,样式如下:  这样看起来是没什么问题的,但当我选择时,在框中显示的内容和筛选条件的内容就出错了: 这里其实是选择了 采矿业 -- 石油和天然气开采业 ,但显示框中是 林业,筛选条件的内容也有问题: 这里没有显

    2024年02月10日
    浏览(27)
  • 解决VIvado编程中遇到的bug I

    解决VIvado编程中遇到的bug I 1.[DRC MDRV-1] Multiple Driver Nets: Net has multiple drivers: GND/G, and VCC/P. 解决: 这个问题很常见,reg变量被在不同的always模块同时赋值 2.[Designutils 20-1307] Command ‘get_ports{led4_tri_io[0]}’ is not supported in the xdc constraint file. [“***/test_EMIO_LED.srcs/constrs_1/new/system.xdc”

    2023年04月26日
    浏览(24)
  • 软件测试技术分享丨遇到bug怎么分析?

    为什么定位问题如此重要? 可以明确一个问题是不是真的“bug” 很多时候,我们找到了问题的原因,结果发现这根本不是bug。原因明确,误报就会降低 多个系统交互,可以明确指出是哪个系统的缺陷,防止“踢皮球”,提高问题解决的效率 增强开发对测试的信任度,沟通更

    2024年02月10日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包