文章目录
初始化数据库
引入数据库的目的不止是为了存储,更多地也是为了便于查询,否则也没必要用一个Text控件来展示信息了。
所以一个正常的工作逻辑是,一打开热榜分析系统,也就同步打开数据库,然后随用随查,而打开数据库之后需要检查是否已经建立了热榜表格,如果没建立那么就建立一下。
所以在初始化函数中新增一个self.initSql()
,内容如下
python
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改成下列形式
python
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函数
python
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
数据库写入
最麻烦的工作结束了,现在可以开始数据库写入
python
# 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)
最后,在关闭窗口时,别忘了存储和关闭数据库,首先在初始化函数中添加
python
self.root.protocol("WM_DELETE_WINDOW", self.exit)
其self.exit内容如下
python
def exit(self):
self.dbCSDN.commit()
self.dbCSDN.close()
self.root.destroy()
为了确保的的确确把数据写入了数据库,可以用SQLiteStudio查看一下,