python爬虫-多线程-数据库——WB用户

news2024/11/26 16:46:39

数据库database的包:

Python操作Mysql数据库-CSDN博客

效果:

控制台输出:

数据库记录:

全部代码:

import json
import os
import threading
import traceback

import requests
import urllib.request
from utils import make_headers, base64_encode_img, url_img_cv2img
from database import MyDataBase


class WeiboUserCrawler(threading.Thread):
    def __init__(self, user_id: str, path: str = "weibo", proxy_addr: str = "122.241.72.191:808"):
        super(WeiboUserCrawler, self).__init__(target=self.run)
        self.user_id = user_id
        self.path = path
        self.proxy_addr = proxy_addr
        self.url = 'https://m.weibo.cn/api/container/getIndex?type=uid&value=' + self.user_id

        self.container_id = self.get_container_id(self.url)
        self.page = 1  # 微博页数
        self.pic_num = 0  # 图片编号
        self.flag = True

        self.wb_db = MyDataBase("localhost", "123456", charset="utf8mb4")
        self.users_sheet = "user_info"  # 所有用户信息表
        self.user_sheet = "user_" + self.user_id  # 单个用户内容表
        self.imgs_sheet = "user_imgs"  # 所有用户图片表

        self.create_file()
        self.create_db_tables()
        print("####" * 10)

    # 创建文件夹
    def create_file(self):
        if not os.path.exists(self.path):
            os.makedirs(self.path)
        if not os.path.exists(self.path + "/" + self.user_id):
            os.makedirs(self.path + "/" + self.user_id)

    # 创建三张表
    def create_db_tables(self):
        self.wb_db.connect()
        kwargs = {
            "id": "int primary key auto_increment",
            "name": "varchar(128)",
            "user_id": "varchar(20)",
            "profile_url": "varchar(200)",
            "verified": "varchar(50)",
            "profile_image_url": "varchar(200)",
            "description": "text",
            "follows": "varchar(50)",
            "fans": "varchar(50)",
            "gender": "varchar(8)",
            "lv": "tinyint"
        }
        self.wb_db.create_table(self.users_sheet, kwargs)
        kwargs = {
            "id": "int primary key auto_increment",
            "u_id": "varchar(20)",
            "url": "varchar(200)",
        }
        self.wb_db.create_table(self.imgs_sheet, kwargs)
        kwargs = {
            "id": "int primary key auto_increment",
            "page": "int",
            "locate": "varchar(128)",
            "created_time": "varchar(128)",
            "content": "text",
            "praise": "varchar(50)",
            "comments": "text",
            "reposts": "varchar(50)",
        }
        self.wb_db.create_table(self.user_sheet, kwargs)

    def use_proxy(self, url):
        req = urllib.request.Request(url)
        req.add_header("User-Agent", make_headers()["User-Agent"])
        proxy = urllib.request.ProxyHandler({'http': self.proxy_addr})
        opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler)
        urllib.request.install_opener(opener)
        data = urllib.request.urlopen(req).read().decode('utf-8', 'ignore')
        return data  # 返回的是字符串

    def get_container_id(self, url):
        data = self.use_proxy(url)
        # 通过json从获取的网页数据中,找到data
        content = json.loads(data).get('data')
        # 从data中找到container_id
        for data in content.get('tabsInfo').get('tabs'):
            if data.get('tab_type') == 'weibo':
                container_id = data.get('containerid')
                return container_id

    def get_user_info(self):
        data = self.use_proxy(self.url)
        # 通过json从获取的网页数据中,找到data
        content = json.loads(data).get('data')
        # 从data数据中获取下列信息
        profile_image_url = content.get('userInfo').get('profile_image_url')
        description = content.get('userInfo').get('description')
        profile_url = content.get('userInfo').get('profile_url')
        verified = content.get('userInfo').get('verified')
        follows = content.get('userInfo').get('follow_count')
        name = content.get('userInfo').get('screen_name')
        fans = content.get('userInfo').get('followers_count')
        gender = content.get('userInfo').get('gender')
        lv = content.get('userInfo').get('urank')
        data = f"微博昵称:{name}\n微博主页地址:{profile_url}\n微博头像地址:{profile_image_url}\n" \
               f"是否认证:{verified}\n微博说明:{description}\n关注人数:{follows}\n" \
               f"粉丝数:{fans}\n性别:{gender}\n微博等级:{lv}\n"
        print(data)
        path = f"{self.path}/{self.user_id}/{self.user_id}.txt"
        with open(path, 'a', encoding='utf-8') as f:
            f.write(data)

        # 数据库存用户
        users_sheet_field = (
            "name", "user_id", "profile_url", "verified", "profile_image_url", "description", "follows",
            "fans", "gender", "lv")
        data = [name, self.user_id, profile_url, verified, profile_image_url, description, follows, fans, gender,
                lv]
        res = self.wb_db.select_table_record(self.users_sheet, f"where user_id={self.user_id}")
        for i in res:
            if self.user_id in i:
                print("该用户已在数据库!")
                return
        self.wb_db.insert_data(self.users_sheet, users_sheet_field, data)

    # 存图下载图
    def save_img(self, mblog):
        try:
            if mblog.get('pics'):
                pic_archive = mblog.get('pics')
                for _ in range(len(pic_archive)):
                    self.pic_num += 1
                    img_url = pic_archive[_]['large']['url']
                    img_data = requests.get(img_url)
                    path = f"{self.path}/{self.user_id}/{self.user_id}_{self.pic_num}{img_url[-4:]}"
                    with open(path, "wb") as f:
                        f.write(img_data.content)
                    # 数据库存图
                    imgs_sheet_field = ("u_id", "url")
                    data = [self.user_id, img_url]
                    self.wb_db.insert_data(self.imgs_sheet, imgs_sheet_field, data)
        except Exception as err:
            traceback.print_exc()

    def save_data(self, j, mblog, cards):
        path = f"{self.path}/{self.user_id}/{self.user_id}.txt"
        attitudes_count = mblog.get('attitudes_count')
        comments_count = mblog.get('comments_count')
        created_at = mblog.get('created_at')
        reposts_count = mblog.get('reposts_count')
        scheme = cards[j].get('scheme')
        text = mblog.get('text')
        with open(path, 'a', encoding='utf-8') as f:
            f.write(f"----第{self.page}页,第{j}条微博----" + "\n")
            f.write(f"微博地址:{str(scheme)}\n发布时间:{str(created_at)}\n微博内容:{text}\n"
                    f"点赞数:{attitudes_count}\n评论数:{comments_count}\n转发数:{reposts_count}\n")
        # 数据库存微博内容
        user_sheet_field = ("page", "locate", "created_time", "content", "praise", "comments", "reposts")
        data = [self.page, scheme, created_at, text, attitudes_count, comments_count, reposts_count]
        self.wb_db.insert_data(self.user_sheet, user_sheet_field, data)

    def process_data(self, data):
        content = json.loads(data).get('data')
        cards = content.get('cards')
        if len(cards) > 0:
            for j in range(len(cards)):
                print(f"-----正在爬取{self.user_id}:第{self.page}页,第{j + 1}条微博------")
                card_type = cards[j].get('card_type')
                if card_type == 9:
                    mblog = cards[j].get('mblog')
                    self.save_img(mblog)
                    self.save_data(j, mblog, cards)
            self.page += 1
        else:
            self.flag = False

    def run(self):
        try:
            self.get_user_info()
            while True:
                weibo_url = f"{self.url}&containerid={self.container_id}&page={self.page}"
                try:
                    data = self.use_proxy(weibo_url)
                    self.process_data(data)
                    if not self.flag:
                        print(f">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>已完成{self.user_id}")
                        self.wb_db.close()
                        break
                except Exception as err:
                    print(err)
        except Exception as err:
            print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>异常退出!')
            self.wb_db.close()


if __name__ == '__main__':
    # 1669879400   # 热巴
    # 5372556014 # 李一桐
    # 1662262590 # 张予曦
    # uid = "1669879400"
    # wb = WeiboUserCrawler(uid)
    # wb.start()
    uids = ["1669879400", "5372556014", "1662262590"]
    for uid in uids:
        t = WeiboUserCrawler(uid)
        t.start()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1426141.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

博客文章质量分数列表【分页、排序、搜索】

文章目录 一、分析二、代码1、前端代码2、后端代码 三、实现效果四、总结1、出现安全验证2、401 Unauthorized: [no body] 一、分析 官方提供的质量分查询入口:CSDN质量分 输入我们要查的文章即可,比如:https://blog.csdn.net/qq_36433289/a…

开发板——X210开发板的SD卡启动方式

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 参考博客: S5PV210 SD卡启动 - 简书 关于存储器的相关基础知识,见博文: 外存——SD卡/iNand芯片与S5PV210的SD/MMC/iNand控制器-CSDN博客 RAM、ROM和FLASH三…

了解WPF控件:TreeView常用属性与用法(十五)

引言 TreeView控件是WPF(Windows Presentation Foundation)中用于显示分层数据的常用控件。这个控件允许用户以树形结构展示数据,使得数据更加清晰易懂。在创建文件浏览器、组织结构图等应用程序时,TreeView控件非常有用。 Tree…

R语言入门笔记2.0

1.创建数据框 在R语言中,可以使用data.frame函数来创建数据框。以下是一个简单的示例,这段R语言代码创建了一个名为student的数据框,其中包含了学生的ID、性别、姓名和出生日期,首先创建一个包含学生出生日期的向量,再…

探秘本庄村果园预售系统的技术之旅

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

【MCAL】TC397+EB-tresos之GPT配置实战 - 定时器

本篇文章介绍了在TC397平台使用EB-tresos对GPT驱动模块进行配置的实战过程,不仅介绍了使用GTM来实现定时器的方案,还介绍了基于GPT12来实现连续定时器的实例。因为GTM是德国博世公司开发的IP,而英飞凌的芯片集成了这个IP,并在这个基础上搭建了…

Pytest 与allure测试报告集成

通过Feature, story, step 记录测试的功能,场景及测试步骤 # login.pylogin_func函数 传入参数是name 和 password 当输入的name和password与数据库db_data中数据一致时,返回“XXX成功登录系统!” 当输入的name存在于数据库db_data但密码不正…

双非本科准备秋招(13.1)—— 力扣 栈、队列与堆

1、103. 二叉树的锯齿形层序遍历 昨天做的二叉树的层序遍历,把代码直接拿过来。 这个题要求的是一个Z型遍历,如下图。 用一个变量f记录正反顺序,然后使用LinkedList记录答案,下图可以看到LinkedList继承了Deque,所以…

【知识图谱--第一讲概论】

深度学习–连接主义 知识图谱–符号主义 表示 有属性图和RDF图两种 RDF由三元组表示:Subject - Predicate - Object 存储 图数据库 抽取 融合 推理 问答 图算法

Linux:进程信号的概念与产生原理

文章目录 信号的概念实践信号关于前台和后台进程的操作 操作系统与外设信号的产生signal系统调用 前面的篇章结束了信号量的话题,那么接下来引入的是信号的话题,信号和信号量之间没有任何关系,只是名字比较像 信号的概念 在生活中存在各种各…

linux麒麟系统安装mongodb7.0

1.mogedb下载 下载的是他tar包 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz wget -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz 也可以下载rpm包 2.将包上传至服务器并解压 #进入目录 并解压 cd /opt/ tar…

Linux ---- Shell编程之免交互

一、Here Document 多行重定向 1、Here Document定义 使用I/O重定向的方式将命令列表提供给交互式程序标准输入的一种替代品Here Document 是标准输 入的一种替代品,可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个文件…

技术科普 | 机器视觉5大关键技术及其常见应用

计算机视觉是指:让机器通过数字图像或视频等视觉信息来模拟人类视觉的过程,以达到对物体的理解、识别、分类、跟踪、重建等目的的技术。它是人工智能领域中的一个分支,涉及图像处理、模式识别、机器学习、深度学习等多个领域。 随着人工智能和…

7.2、子集求和问题与背包密码系统

7.2、子集求和问题与背包密码系统 一、数学描述 1.1、第一种描述 20 世纪 70 年代末,默克尔和赫尔曼首次尝试将密码系统建立在一个 NP-完全问题上。他们使用了以下数学问题的一个版本,该问题是对经典knapsack问题的概括。 子集和问题 假设你有一个正…

数据结构——链式二叉树(3)

本篇文章我们依然讲解链式二叉树的OJ题; 一、二叉树的层序遍历 层序遍历即从根节点开始一层一层的遍历。我们可以运用队列的先进先出特性实现! //层序遍历 void a(BTNode* root) {Que qhead;Queueinit(&qhead);//先入队根节点if(root)QueuePush(&…

C#,计算几何,随机点集之三角剖分的德劳内(Delaunay)算法的源代码

一、三角剖分Delaunay算法简介 点集的三角剖分(Triangulation),对数值分析(比如有限元分析)以及图形学来说,都是极为重要的一项预处理技术。尤其是Delaunay三角剖分,由于其独特性,关…

LeetCode: 160.相交链表(令人赞叹的优雅)

160. 相交链表 - 力扣(LeetCode) 目录 官方双指针解法: 博主的辣眼代码: 每日一表情包: 博主还未学习哈希表,所以介绍的是双指针法,此题的哈希表解法时O(nm)空O&…

MySQL窗口函数--lead()函数

lead()函数: 查询当前行向下偏移n行对应的结果 该函数有三个参数:第一个为待查询的参数列名,第二个为向下偏移的位数,第三个参数为超出最下面边界的默认值。 如下代码: 查询向下偏移 2 位的年龄 SELECT user_id,user…

JavaScript高级:深浅拷贝

目录 1 引言 2 浅拷贝 2.1 拷贝数组 1.2 拷贝对象 3 赋值操作和浅拷贝的比较 4 深拷贝 4.1 前置知识 --> 递归函数 4.2 使用递归实现深拷贝 4.3 js库中的lodash里面的cloneDeep内部实现深拷贝 4.4 利用JSON实现深拷贝 深浅拷贝只针对引用数据类型 1 引言 假如我们…

leetcode 19 , 118

19 .删除链表倒数第n个节点 思路1: 我首先想到的就是使用两个loop来进行解决: 遍历所有节点,得到需要删除节点的位置。再遍历一边所有节点,找到需要删除节点进行删除。 解决方案1: class Solution {public ListNod…