CSDN热榜分析6:将实时爬取的热榜数据导入sqlite
文章目录
- 初始化数据库
- 接口更改
- 数据库写入
初始化数据库
引入数据库的目的不止是为了存储,更多地也是为了便于查询,否则也没必要用一个Text控件来展示信息了。
所以一个正常的工作逻辑是,一打开热榜分析系统,也就同步打开数据库,然后随用随查,而打开数据库之后需要检查是否已经建立了热榜表格,如果没建立那么就建立一下。
所以在初始化函数中新增一个self.initSql()
,内容如下
def initSql(self):self.dbCSDN = sqlite3.connect('csdn.db')HEADS = 'create table heat (日期 int, 时间 int, 热榜 text, 序号 int, 'HEADS += '标题 text, 作者 text, 浏览 int, 'HEADS += '评论 int, 收藏 int, 热度 int)'try: self.dbCSDN.execute(HEADS)except: pass
如果已经有了heat表格,那么再去创建就会报错,所以只要pass掉就可以了。
接口更改
相比于读取完所有数据之后一次性导入数据库,在数据爬取的过程中导入显然更加自然。
另一方面,读取数据需要新开一个线程,而sqlite3模块并不支持跨线程操作,所以只能等数据传回来再操作,
这两个条件,就基本框定了技术方案,只能在爬虫回调时写入数据库,但之前的回调函数是直接把当前爬取的数据列表传回,而非单条数据,所以需要花费一点精力修改接口,主要就是把大部分调用回调函数的地方,从类似callback(blogs)改为callback(b),然后将backOneSubHeat改成下列形式
def backOneSubHeat(self, L, info, field=None):if field not in self.subHeats:self.subHeats[field] = []if L != []:self.subHeats[field].append(L)if info.endswith("完毕"):n = len(self.subHeats[field])self.addLogs(f"共读取了{field}领域{n}篇博客")
同时为了接口统一,之前的backAllSubHeat就没有必要存在了,同时更改getAllSubHeatInfos函数
def getAllSubHeatInfos(callback):blogs = {}for key in SUB_HEATS:func = lambda L, info : callback(L, info, key)func([], f"正在读取{key}领域热榜")blogs[key] = getHeatInfos(func, key)func([], f"{key}已经读取完成")func([], f"所有领域热榜都已读取完成")return blogs
数据库写入
最麻烦的工作结束了,现在可以开始数据库写入
# L为回传的数据
def importHeatToSql(self, L, field):CODE = "insert into heat values (date('now'), time('now'), "bInfo = ', '.join([f"'{iL}'" for iL in L])c = CODE + f"'{field}', {bInfo})" try: self.dbCSDN.execute(c)except Exception as e: print(e, c)
最后,在关闭窗口时,别忘了存储和关闭数据库,首先在初始化函数中添加
self.root.protocol("WM_DELETE_WINDOW", self.exit)
其self.exit内容如下
def exit(self):self.dbCSDN.commit()self.dbCSDN.close()self.root.destroy()
为了确保的的确确把数据写入了数据库,可以用SQLiteStudio查看一下,