用tkinter+selenium做一个CSDN热榜爬虫

2023-09-21 09:45:00

自从学会了分析热榜,就是CSDN热榜分析,每天都要爬下来分析一下热榜都在干什么。但脚本运行到底还是不方便,所以接下来就想办法将其做成一个带有界面的热榜爬虫

UI设计

做一个热榜爬虫的交互式界面,只需要两个按钮外加两个信息框就足够了,所以布局极其简单

class TestSTL:
    def __init__(self):
        self.root = tk.Tk()
        self.root.geometry("600x300+200+20")
        self.root.title("CSDN分析")
        self.initVars()
        self.initWidgits()
        self.root.mainloop()
    
    def initVars(self):
        self.heatBlogs = []
        self.subHeats = {}
        self.infoCSDN = tk.StringVar()

    def initWidgits(self):
        frmCtrl = ttk.LabelFrame(self.root, text="CSDN工具")
        frmCtrl.pack(side=tk.TOP, fill=tk.X)
        self.setFrmCtrl(frmCtrl)

        frmInfo = ttk.LabelFrame(self.root, text="反馈信息")
        frmInfo.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
        ttk.Label(frmInfo, textvariable=self.infoCSDN).pack(side = tk.TOP, fill=tk.X)
        self.infoCSDN.set("无反馈")

        self.setFrmInfo(frmInfo)
    
    def setFrmCtrl(self, frm):
        frmPack = dict(side=tk.TOP, fill=tk.X)
        frmHeat = ttk.Frame(frm)
        frmHeat.pack(**frmPack)
        ttk.Label(frmHeat, width=10, text="热榜分析").pack(side=tk.LEFT)
        ttk.Button(frmHeat, width=10, text="爬取热榜",
            command=self.btnHeatCrawler).pack(side=tk.LEFT)

        ttk.Button(frmHeat, width=10, text="导出热榜",
            command=self.mbExportHeat).pack(side=tk.LEFT)
        
    def setFrmInfo(self, frm):
        scroll = ttk.Scrollbar(frm)
        scroll.pack(side=tk.RIGHT,fill=tk.Y)
        self.logTxt = tk.Text(frm)
        self.logTxt.pack(side=tk.TOP, fill=tk.BOTH, padx=5, pady=5, expand=True)
        self.logTxt.config(yscrollcommand=scroll.set)
        scroll.config(command=self.logTxt.yview)

    # 热榜
    def btnHeatCrawler(self):
        pass

    def mbExportHeat(self):
        pass

    def addLogs(self, text):
        self.logTxt.insert("end", f"{text}\n")
        self.logTxt.see("end")

在setFrmCtrl中,除了热榜分期的标签外,设置了两个按钮,分别是爬取热榜和导出热榜,二者分别绑定了两个函数btnHeatCrawler和mbExportHeat,这两个函数暂时还没实现。

在CSDN工具Frame下面,是信息界面,信息界面封装了两个组件,一个用于返回实时信息,是个Label,绑定了名为self.infoCSDN的Label;另一个是多行文本组件Text,并为其设置了addLogs函数,用于快速添加内容。布局结果如下

在这里插入图片描述

函数封装

尽管此前已经多少知道如何用selenium爬取热榜了,但所有代码都是以脚本的形式写出来的,并不适合调用。所以接下来就要把这些代码函数化,首先是打开Edge的函数

# 打开Edge
def openEdge(url):
    op = webdriver.EdgeOptions()
    op.add_argument('--headless')
    driver = webdriver.Edge(options=op)
    driver.get(url)
    return driver

这里用到了EdgeOptions,其参数headless表示不必打开Edge,而可以后台运行,不然Edge总会跳出来,影响其他工作。

然后就是用于热榜爬取的主要函数,封装如下,其中callback是一个回调函数,方便将运行信息传给用户界面,后面的key,则考虑到以后会爬取各领域热榜,于是预留一个接口。

# 输入回调函数
def getHeatInfos(callback, key=None):
    nBlogs = 100
    driver = openEdge('https://blog.csdn.net/rank/list')

    titleClass = "floor-rank-item"
    ts= []
    # 获取100篇热榜博客
    while len(ts) < nBlogs:
        script = "window.scrollTo(0,document.body.scrollHeight)"
        driver.execute_script(script)
        ts = driver.find_elements(By.CLASS_NAME, titleClass)
        time.sleep(0.5)
        info = f"已读取到{len(ts)}篇热榜博客"
        if callback: callback([], info)
        
    callback([], f"已读取到所有热榜博客,开始处理")
    blogs = []
    for t in ts:
        ws = t.text.split('\n')
        blogs.append([ws[i] for i in [0, 1, 10, 2, 4, 6, 8]])
        b = blogs[-1]
        callback(blogs, f"正在处理第{b[0]}篇博客,热度{b[-1]}")
    callback(blogs, f"全部热榜博客处理完毕")
    return blogs

这个函数的代码几乎都来自CSDN热榜分析

最后,是导出CSV的函数

def saveAsCSV(path, infos, title=['id','name', 'date', '']):
    with open(path, 'w', newline='', encoding='utf8') as f:
        w = csv.writer(f)
        w.writerow(title)
        for i in infos: 
            try: w.writerow(i)
            except : continue

功能实现

最后,实现窗口程序对热榜爬取函数的调用逻辑。考虑到爬虫往往是个耗时的操作,所以必须使用多线程。

from threading import Thread

最终热榜爬取函数的内容如下,其实核心代码就只有一行,表示开启一个线程来执行getHeatInfo,并把self.backHeatCrawler作为参数输入了进去。

backHeatCrawler是用于反馈信息的回调函数,其功能如其参数一样,共有两个,一个是保存爬取到的博客信息,二则是展示爬虫进度。

# 热榜
def btnHeatCrawler(self):
    Thread(target = getHeatInfos,
        args=(self.backHeatCrawler,), daemon=True).start()

def backHeatCrawler(self, blogs, info):
    self.heatBlogs = blogs
    self.infoCSDN.set(info)
    if info.endswith("完毕"):
        self.addLogs(f"共读取了{len(self.heatBlogs)}热榜博客")

最后完成数据导出工作,其主要功能就是调用saveAsCSV函数,只不过其中加入了文件名对话框等交互方式。

def mbExportHeat(self):
    heatHead = ["序号", "标题", "作者", "浏览", "评论", "收藏", "热度"]
    self.mbExport(self.heatBlogs, heatHead, "热榜博客")
    
def mbExport(self, lst, title, info):
    self.infoCSDN.set(f"正在保存{info}")
    path = asksaveasfilename(filetypes=[("数据文件", "csv")], 
        defaultextension='.csv')
    if path=="":
        self.infoCSDN.set(f"未保存{info}")
        return
    saveAsCSV(path, lst, title=['id'])
    self.infoCSDN.set(f"{info}保存成功")
    self.addLogs(f"{info}保存成功")

最终演示效果如下

在这里插入图片描述

更多推荐

为Electron-log 设置日志颜色

使用Electron-log为你的Electron应用添加日志颜色在Electron应用中,有效的日志记录是一项不可或缺的任务,它可以帮助你跟踪应用程序的运行状况、调试问题以及监视用户体验。为了提高日志的可读性,你可以使用Electron-log以及Node.js中的Chalk模块来为不同的日志级别添加颜色和样式。安装

浅谈建筑能耗智能监测平台发展现状及未来趋势

安科瑞华楠摘要:文章以每年发布的上海市国家机关办公建筑和大型公共建筑能耗监测及分析报告变化为切入点,分析了历年能耗分析报告的内容和功能变化;介绍了上海市国家机关办公建筑和大型公共建筑能耗监测平台发展和应用历程;揭示了当下显现的问题,并以问题为导向,预测了未来发展的趋势。关键词:国家机关办公建筑和大型公共建筑;能耗监测;

洁净室/净化车间:洁净等级划分及标准、检测方法及流程解读

无尘车间的发展与现代工业、尖端技术紧密的联系在一起。目前在生物制药、医疗卫生、食品日化、电子光学、能源、精密器械等行业运用已经相当的普遍且成熟。空气洁净度等级(aircleanlinessclass):洁净空间单位体积空气中,以大于或等于被考虑粒径的粒子最大浓度限值进行划分的等级标准。国内按空态、静态、动态对无尘车间进

MySQL详细案例 1:MySQL主从复制与读写分离

文章目录1.MySQL主从复制1.1使用场景1.2MySQL的复制类型1.3主从复制的作用1.4主从复制的工作过程1.5实现MySQL主从复制1.5.1前置准备1.5.2主服务器mysql配置1.5.3从服务器1mysql配置1.5.4从服务器2mysql配置1.5.5测试1.6主从复制的3种同步模式1.6.1异步复制

实时数仓混沌演练实践

一、背景介绍目前实时数仓提供的投放实时指标优先级别越来越重要,不再是单独的报表展示等功能,特别是提供给下游规则引擎的相关数据,直接对投放运营的广告投放产生直接影响,数据延迟或者异常均可能产生直接或者间接的资产损失。从投放管理平台的链路全景图来看,实时数仓是不可或缺的一环,可以快速处理海量数据,并迅速分析出有效信息,同时

Java JVM分析利器JProfiler 结合IDEA使用详细教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、JProfiler是什么?二、我的环境三、安装步骤1.Idea安装JProfiler插件1.下载程序的安装包四、启动前言对于我们Java程序员而言,肯定需要对项目工程进行JVM监控分析,最终选择jprofiler,它可以远程链接,使用方便,

opencv图像像素类型转换与归一化

文章目录opencv图像像素类型转换与归一化1、为什么对图像像素类型转换与归一化2、在OpenCV中,`convertTo()`和`normalize()`是两个常用的图像处理函数,用于图像像素类型转换和归一化;(1)`convertTo()`函数用于将一个`cv::Mat`对象的像素类型转换为另一种类型。它的基本用法

第8章 MySQL的数据目录

8.1数据库和文件系统的关系像InnoDB、MyISAM这样的存储引擎都是把表存储在磁盘上的,而操作系统用来管理磁盘的又被称为文件系统,所以用专业一点的话来表述就是:像InnoDB、MyISAM这样的存储引擎都是把表存储在文件系统上的。当我们想读取数据的时候,这些存储引擎会从文件系统中把数据读出来返回给我们,当我们想写

公私钥非对称加密 生成和验证JSON Web Token (JWT)

前言这是我在这个网站整理的笔记,关注我,接下来还会持续更新。作者:神的孩子都在歌唱公私钥非对称加密生成和验证JSONWebToken什么是JSONWebToken(JWT)Java程序中生成和验证JWT代码解析什么是JSONWebToken(JWT)JSONWebToken(JWT)是一种轻量级的身份验证和授权机制,由

【Linux 之二】Ubuntu下开发环境的搭建(NFS \ SSH \ FTP \ Smba \ ...)

目前正在进行Linux相关项目的开发,而我的Linux开发是在Ubuntu(版本20.04)下进行的,为此需要搭建很多Linux相关的开发环境,方便工作的进行。这里主要是对各种开发环境的搭建做一个总结记录,方便后面查阅,也方便在Linux开发之路上遇到困难的各位同仁。好了,废话不多说,直接罗列各种开发环境的安装步骤等。

Java 多线程

目录线程相关概念线程基本使用1.继承Thread类,重写run方法示例代码程序示意图2.实现Runnable接口,重写run方法示例代码*应用案例代码理解3.继承Threadvs实现Runnable的区别4.多线程售票问题引出同步互斥问题5.线程终止代码示意图线程常用方法第一组示例代码第二组示例代码用户线程和守护线程示

热文推荐