python爬虫———多线程threading模块爬取抖音用户信息

2023-11-12

爬虫背景:
由于原来的数据库中有1.5亿左右的用户id,但是其中有1.2亿的用户资料是不完整的(没有粉丝数量,点赞数量等,算是无用数据),现在老板要求将这些没有资料的用户更新信息,咋办?
刚开始的想法是使用主从模式+scrapy爬取,但是写着写着觉得麻烦(写python的都很懒,scrapy还是比较臃肿的),然后突然想到,python中的多线程,处理爬虫这种存在大量io的操作时,多线程是非常有用的,而且省服务器资源(其他的爬虫也在服务器,能省一点是一点,毕竟是自己用的,太卡的话上班都不爽),开始干!

不怕笑话,就2个函数。。。。
我觉得代码不重要,重要的是处理的方式,以及多多利用多线程的这种方法,各种原因不想搭scrapy的时候,只需要几行代码,就能将爬虫速度提升n倍,岂不美哉?
一.
说一下我的爬虫思路(架构?),不存在花里胡哨的操作与各种专业名词,只讲究实用
1.我的整个爬虫所用到的有django1.8.2 + requests + redis + pgsql 由于这里django的作用很小(代码中有讲),就不讲了
2.django操作pg存数据,redis作为队列
3.由于使用了redis作为队列,所以不存在多线程中的锁(Lock)的隐患,队列本身就是安全的,锁来锁去什么的不用管
4.我的这个模式,自认为还是比较好用的,简单快捷,剩下的会在下面代码中注释说明,只copy了部分代码块

二.
说一下我这个里面的多线程的注意事项吧:
1.将爬虫用while True包裹起来,目的是为了保持线程的存活,至于单个线程的退出条件,可以用for,while之类的条件来限制
2.函数中不要用return,不要用return,不要用return,重要的事情说三遍

@staticmethod
    def get_user_info_from_app_new(**kwargs):
        while True:
            user_id = redis_client.rpop(REDIS_DOUYIN_NULL_INFO_USER)  # 从redis中取一个user_id
            retry_list = []
            for retry in range(150):  # 额,由于设备号不足的原因,导致一个user_id的请求最多重复请求150次,只要其中任意一次成功,就ok
                url_as, url_cp, iid, device_id, openudid = DouyinCrawler.get_params_for_app(**kwargs)
                device_info = redis_client.srandmember(REDIS_DOUYIN_SET_DEVICE_TYPE_BRAND)  # str 每一次请求都是随机不同的设备型号
                device = device_info.split(';')
                d_type = device[0]
                d_brand = device[1]
                # print 'device_type', d_type
                # print 'device_brand', d_brand
                url = 'https://aweme-eagle.snssdk.com/aweme/v1/user/?user_id={}&retry_type=no_retry&iid={}&device_id={}&ac=wifi&channel=xiaomi&aid=1128&app_name=aweme&version_code=179&version_name=1.6.8&device_platform=android&ssmix=a&device_type={}&device_brand={}&language=zh&os_api=22&os_version=5.1.1&openudid={}&manifest_version_code=179&resolution=720*1280&dpi=240&update_version_code=1792&_rticket={}&ts={}&as={}&cp={}'.format(
                    user_id, iid, device_id, d_type, d_brand, openudid, int(time.time() * 1000), int(time.time()), url_as,
                    url_cp)
                req = requests.get(url, headers=app_headers)
                try:
                    jdata = json.loads(req.content)
                except ValueError as e:
                    logging.info('retry for no json data decode, {}, {}'.format(user_id, req.content))
                    continue
                if jdata['status_code'] != 0 or not jdata.get('user'):
                    logging.error('get user info from app error, {}, {}, times:{}'.format(user_id, jdata, retry))
                    retry_list.append(retry)
                    # return None
                else:
                    try:
                        douyin_id = user_id
                        user = jdata.get('user')
                        city = user.get('city')
                        if user.get('cover_url') is None and user.get("nickname", u'已重置') == u"已重置":
                            logging.info('user has been limited, {}, {}'.format(user_id, jdata))
                        locations = user.get('location')
                        activity_digg_count = user['activity']['digg_count']
                        use_music_count = user['activity']['use_music_count']
                        apple_account = user['apple_account']
                        head_url = user['avatar_larger']['url_list'][0]
                        gender = user.get('gender')
                        bind_phone = user['bind_phone']
                        birthday = user['birthday']
                        country = user['country']
                        province = user['province']
                        constellation_id = user['constellation']
                        verify_info = user['custom_verify']
                        dongtai_count = user['dongtai_count']
                        like_num = user['favoriting_count']
                        follower_quantity = user['follower_count']
                        followed_quantity = user['following_count']
                        ins_id = user['ins_id']
                        mplatform_followers_count = user['mplatform_followers_count']
                        name = user['nickname']
                        room_id = user['room_id']
                        musician_digg_count = user.get('original_musician', {}).get('digg_count')
                        musician_music_count = user.get('original_musician', {}).get('music_count')
                        musician_music_used_count = user.get('original_musician', {}).get('music_used_count')
                        share_qrcode_uri = user['share_qrcode_uri']
                        short_id = user['short_id']
                        signature = user['signature']
                        total_digg_count = user['total_favorited']
                        uid = user['uid']
                        unique_id = user['unique_id']
                        weibo_name = user.get('weibo_name')
                        weibo_url = user.get('weibo_url')
                        feed_num = user.get('aweme_count')

                        with_fusion_shop_entry = user.get('with_fusion_shop_entry')
                        with_item_commerce_entry = user.get('with_commerce_entry')
                        verification_type = user.get('verification_type')
                        custom_verify = user.get('custom_verify')
                        enterprise_verify_reason = user.get('enterprise_verify_reason')

                        payloads = {
                            'user': user,
                            'city': city,
                            'locations': locations,
                            'activity_digg_count': activity_digg_count,
                            'use_music_count': use_music_count,
                            'apple_account': apple_account,
                            'head_url': head_url,
                            'gender': gender,
                            'bind_phone': bind_phone,
                            'birthday': birthday,
                            'country': country,
                            'province': province,
                            'constellation_id': constellation_id,
                            'verify_info': verify_info,
                            'dongtai_count': dongtai_count,
                            'like_num': like_num,
                            'follower_quantity': follower_quantity,
                            'followed_quantity': followed_quantity,
                            'ins_id': ins_id,
                            'mplatform_followers_count': mplatform_followers_count,
                            'name': name,
                            'room_id': room_id,
                            'musician_digg_count': musician_digg_count,
                            'musician_music_count': musician_music_count,
                            'musician_music_used_count': musician_music_used_count,
                            'share_qrcode_uri': share_qrcode_uri,
                            'short_id': short_id,
                            'signature': signature,
                            'total_digg_count': total_digg_count,
                            'uid': uid,
                            'unique_id': unique_id,
                            'weibo_name': weibo_name,
                            'weibo_url': weibo_url,
                            'feed_num': feed_num,
                            'with_fusion_shop_entry': with_fusion_shop_entry,
                            'with_item_commerce_entry': with_item_commerce_entry,
                            'verification_type': verification_type,
                            'custom_verify': custom_verify,
                            'enterprise_verify_reason': enterprise_verify_reason,
                        }
                        try:
                            # django中有很好用的方法,创建或更新资料,都不用管去重的问题
                            dd_user, is_create = DouyinUser.objects.update_or_create(douyin_id=user_id, defaults={
                                'name': payloads['name'],
                                'verify_info': payloads['verify_info'],
                                'signature': payloads['signature'],
                                'follower_quantity': payloads['follower_quantity'],
                                'followed_quantity': payloads['followed_quantity'],
                                'total_digg_count': payloads['total_digg_count'],
                                'feed_num': payloads['feed_num'],
                                'like_num': payloads['like_num']
                            })
                            print dd_user, 'UPDATE USER INFO SUCCESS'
                            # return payloads  # 注释了 最好不要有return这个东西
                        except:
                            continue
                    except:
                        # 加入到抓取失败的队列
                        # redis_client.lpush(REDIS_DOUYIN_USER_GET_FAILED_LIST, user_id)
                        continue

主函数

    def get_new(self):
        for i in range(10):  # 创建线程池,大小10,想要多少就多少,电脑性能决定
            tt = Thread(target=DouyinCrawler.get_user_info_from_app_new)  #  个人不建议在这里传参
            tt.start()  # 不加锁,不回收,直接start

是的,多加2行就搞定了,速度提升10倍!
最后:
注意!!!!!!!
windows上,把主函数放在main函数里面调用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python爬虫———多线程threading模块爬取抖音用户信息 的相关文章

  • Django 尝试使用错误的数据库用户

    已解决 我使用的是 USERNAME 而不是之前尝试使用 Postgres 驱动程序时使用的 USER 我正在尝试将我的 django 项目连接到 RDS MySQL 数据库 我可以在 MySQL Workbench 和 mysql 命令行
  • 如何确定 Django 中用户何时出现空闲超时?

    我想审核用户在我的 Django 应用程序中遇到空闲超时的情况 换句话说 如果用户的会话 cookie 的过期日期超过了 settings py 中找到的 SESSION COOKIE AGE 用户将被重定向到登录页面 当这种情况发生时 也
  • manage.pysyncdb 不会为某些模型添加表

    今天我的第二个不太熟练的问题 我有一个 django 项目 其中安装了四个应用程序 当我运行manage py syndb时 它只为其中两个创建表 据我所知 我的任何模型文件都没有问题 并且所有应用程序都在我的设置文件中的 INSTALLE
  • 使用 Google App Engine 和 Django 将第三方库 (twilio) 添加到项目中

    每个人 我是这个领域的新手 我使用 django 框架使用 google 应用引擎开发 Web 应用程序 我有一个关于 python lib dir 问题的故障排除 导入错误 没有名为 的模块 我的 appengine config py
  • 带有 ManyToMany 和直通表的 Graphene-django

    我的应用程序有多个多对多关系具有贯穿模型像这样 class Person models Model name models CharField class Group models Model name models CharField m
  • HTML - 使用 JS 根据值更改文本颜色

    我正在使用 Django 创建一个以 HTML 形式显示的表格 我想当数字为负数时将数字的颜色更改为红色 当数字为正数时将数字的颜色更改为绿色 我知道我需要使用 JS 来实现这一点 但我无法让它工作 任何帮助将不胜感激 这是我的 Djang
  • djangorest框架:从序列化器validate()方法设置字段级错误

    我有一个序列化程序 它根据其他字段的值验证字段 在错误响应中 我想将每个字段错误显示为字段错误 而不是显示 non field errors 下的所有内容 如果我提出错误 就会发生这种情况对象级验证方法中的 ValidationError
  • Django/Python:电子邮件回复已更新到站点[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Django GraphQL JWT:tokenAuth 突变返回“str 对象没有属性解码”

    目前 我正在文档页面中运行 django graphqljwt 的基本示例 https django graphql jwt domake io en latest quickstart html https django graphql
  • Django Rest Framework 分页设置 - 内容范围

    6 30 15 我怎样才能让这个问题变得更好并且对其他人更有帮助 反馈会有帮助 谢谢 我使用 DRF 作为 Dojo Dgrid Web 应用程序的服务器端 Dojo 需要来自服务器的内容范围或范围响应 目前它不发送任何内容 因此 dgri
  • 嵌套字段序列化器 - 数据丢失

    与此主题相关 https stackoverflow com questions 27434593 django rest framework 3 0 create or update in nested serializer 你好 我无法
  • 使用 Django REST 框架进行 SAML SSO 身份验证

    我目前正在开发 AngularJS 前端和 Django REST 后端 我一直在使用Django rest auth https github com Tivix django rest auth过去需要对两者之间的连接进行身份验证 但现
  • Django:在单独的线程中使用相同的测试数据库

    我正在使用具有以下数据库设置的测试数据库运行 pytests DATABASES default ENGINE django db backends postgresql psycopg2 NAME postgres USER someth
  • 使用 nginx 在云上部署 django 和 React

    我有一个 digitalocean 服务器 并且已经使用 Gunicorn 和 nginx 部署了 Django 后端服务器 如何在同一台服务器上部署 React 应用程序 您可以构建 React 应用程序并使用 Nginx 提供其静态文件
  • Django:管理中的 AJAX ManyToManyField

    我要显示ManyToManyFields 在 admin 中就像filter horizontal确实如此 但会在用户在过滤器字段中键入内容时填充选项 有很多选项 一次性加载它们需要很多时间 I found django ajax 过滤字段
  • Django在模板中形成多个选择框大小

    我有一个模板
  • ExpectedFailure 被计为错误而不是通过

    我在用着expectedFailure因为有一个我想记录的错误 我现在无法修复 但想将来再回来解决 我的理解expectedFailure是它会将测试计为通过 但在摘要中表示预期失败的数量为 x 类似于它如何处理跳过的 tets 但是 当我
  • 使 django 服务器可以在 LAN 中访问

    我已经安装了Django服务器 可以如下访问 http localhost 8000 get sms http 127 0 0 1 8000 get sms 假设我的IP是x x x x 当我这样做时 从同一网络下的另一台电脑 my ip
  • 如何让 Django 和 ReactJS 协同工作?

    New to Django and even newer to ReactJS I have been looking into AngularJS and ReactJS but decided on ReactJS It seemed
  • Django admin - 更改权限列表

    是否可以更改用户编辑页面中的权限列表 我不想显示所有权限 例如管理日志条目或身份验证组等 如何修改主查询集以排除其中的某些查询集 我的想法来自这个话题 https groups google com forum topic django u

随机推荐

  • Python+selenium的web自动化—PageObject模式解析及案例

    一 PO模式 Page Object 简称PO 模式 是Selenium实战中最为流行 并且是自动化测试中最为熟悉和推崇的一种设计模式 在设计自动化测试时 把页面元素和元素的操作方法按照页面抽象出来 分离成一定的对象 然后再进行组织 做we
  • Qt 绘制炫彩时钟

    录制 2022 09 15 09 44 58 720 思路 1 使用定时器 每秒给 秒值 增加 1 当 秒值 等于 60 时 给 分值 增加1 当分值为60时 给 时值 加1 2 绘制界面时 可以用信号槽触发 也可以调用函数触发 我这里用的
  • 高中辍学后,我转行做了程序员

    大家好 我是黑洋葱 非常普通的一个人 没有太多的故事 可以拿得出手的经历大概就是我从高中辍学后通过自考顺利拿到本科证书 以及通过自学成功转行成IT行业的程序员这一段 今天写下这段完全改变了我人生轨迹的经历 同时也稍微整理了 转行程序员 的学
  • 新手如何使用IntelliJ IDEA创建Java项目

    前提 已安装好IntelliJ IDEA 已安装好jdk 已配置好环境变量 后续会继续推出IntelliJ IDEA的安装 jdk的安装和环境变量的配置 1 第一步打开IntelliJ IDEA 这里默认已经安装好IntelliJ IDEA
  • Elasticsearch 2.x版本往5.x版本迁移数据

    Elasticsearch 2 x版本往5 x版本迁移数据 迁移前准备 1 String类型 2 x版本 跟 5 x版本有一个比较大的改动就是ES的基本类型string字段 5 x版本中使用text keyword字段替代了2 x版本的st
  • Eos离线签名PHP代码

    EOS区块链的钱包服务器Keosd 提供了sign transaction开发接口 允许开发者进行交易签名 但是 如果我们希望自己管理密钥而不是交给keosd管理 应该如何在PHP代码中实现交易的离线签名功能 答案是使用 EosTool 这
  • jq+swiper 实现今日头条App的选项卡效果

  • 新版iTunes 不能安装 ipa 包的五种解决办法

    前言 1 新版iTunes指的是 V12 7 2 新版iTunes界面无应用按钮 即无法安装ipa包 五种方法 1 使用iTools 2 使用低版本的iTunes 1 降低iTunes版本的方法 http bbs feng com read
  • C语言基础入门详解二

    前些天发现了一个蛮有意思的人工智能学习网站 8个字形容一下 通俗易懂 风趣幽默 感觉非常有意思 忍不住分享一下给大家 点击跳转到教程 一 C语言多级指针入门 include
  • 1.5 条件生成对抗网络(CGAN)

    1 什么是CGAN 在CGAN训练期间 生成器学习为训练数据集中的每个标签生成逼真的样本 而鉴别器则学习区分真的样本 标签对与假的样本 标签对 只学习接受真实且样本 标签匹配正确的对 拒绝不匹配的对和样本为假的对 2 生成器 条件标签称为y
  • 深入理解Android相机体系结构之十一

    手机相机的未来与发展 Android相机发展至今 通过开发者对框架的不断优化 算法人员对图像处理算法的不断提升 硬件工程师对硬件性能地不断调教 换来了在某些领域完全可以媲美专业相机的成像效果 这些成绩是有目共睹的 但是我们不能仅仅着眼于过去
  • 开源知识库平台Raneto

    什么是 Raneto Raneto 是一个开源知识库平台 它使用静态 Markdown 文件来支持您的知识库 官方提供了 doc demo 网站 即是帮助文档 也是个 demo 地址 https docs raneto com 准备 项目使
  • 【Yarn】ContainerAllocator Container申请工作机制

    文章目录 1 概述 2 继承体系 3 serviceStart 4 RMContainerAllocator 4 1 构造方法 4 1 1 createAssignedRequests 4 2 serviceInit 4 3 service
  • python 十大经典排序算法

    排序算法可以分为内部排序和外部排序 内部排序是数据记录在内存中进行排序 而外部排序是因排序的数据很大 一次不能容纳全部的排序记录 在排序过程中需要访问外存 常见的内部排序算法有 插入排序 希尔排序 选择排序 冒泡排序 归并排序 快速排序 堆
  • 利用python基于GBDT算法建立轨道交通客流预测模型,并使用网格搜索法进行参数调优...

    你可以使用Python来建立一个基于GBDT算法的轨道交通客流预测模型 为了得到最佳的预测效果 你可以使用网格搜索法来调整模型的参数 网格搜索法是一种通过对参数的不同取值进行试验来选择最优参数的方法
  • 机器学习笔记Machine Learning 之SVD (Singular Value Decomposition) 奇异值分解

    一 特征值和特征向量 A x x Ax lambda x Ax x A 是一个 n n 矩阵 x 是一个 n 维向量
  • webpack的四大核心概念

    webpack中文文档 https doc webpack china org concepts 一 Entry 入口 1 单个入口 简写 语法 语法 entry string Array
  • 3.9 使用Java的文档注释

    Java支持三种形式的注释 前两种是 和 第三种方式被称为文档注释 它以 开始 以 标志结束 文档注释提供将程序信息嵌入程序的功能 开发者可以使用javadoc工具将信息取出 然后转换为HTML文件 文档注释提供了编写程序文档的便利方式 j
  • 简洁直观的飞行器的坐标系与旋转矩阵推导

    Part1 定义5个坐标系 惯性坐标系 载具坐标系 载具1坐标系 载具2坐标系 机体坐标系 总结 载具坐标系与惯性坐标系的关系是平移关系 原点位置不同 载具坐标系绕Z旋转 psi 得到载具1坐标系 载具1坐标系绕Y旋转 theta
  • python爬虫———多线程threading模块爬取抖音用户信息

    爬虫背景 由于原来的数据库中有1 5亿左右的用户id 但是其中有1 2亿的用户资料是不完整的 没有粉丝数量 点赞数量等 算是无用数据 现在老板要求将这些没有资料的用户更新信息 咋办 刚开始的想法是使用主从模式 scrapy爬取 但是写着写着