1. 必要性
- 程序运行过程中可能会出现网络不稳定导致一些数据没有采集到,如果想要完整的数据,我们必须重新开始运行程序。显然,这违背了我们写这个程序的初衷 。把数据保存到硬盘后,重新运行程序时可以跳过已经有的数据。
- 无论在cmd、PowerShell、terminal还是IDLE上运行程序,一旦重启平台,程序的数据都会被删除。保存在硬盘中的数据可以容易被加载到内存中。
- 方便搜索用户是否存在
2. 保存数据
保存数据可以用数据库,把数据保存为JSON或者XML格式。这里为了好玩,用一种简单的方式保存数据。
格式:
- 文件保存在data目录下
- 文件名是用户的UID
- 文本第一行是$SAVE TIME,表示文件的保存时间
- 文本第二行是对象的类型,通过person.classname写入。Person的对象写入Person,WeiboUser的对象写入Weibo
- 文本从第三行开始是属性,以一对#号表示,如#NAME#A NAME,代表person.name = ‘A NAME’
- 关注或粉丝列表只记录用户的UID或个性域名,用分号(;)间隔,最后一条数据后面不加分号
- 文本从第三行开始,第一个字符不是#的行不会被读取
代码:
#Person.py
import datetime
def save(p: Person):
"""
p: an initialization of Person
"""
now = datetime.now()
year, month, day, hour, minute = now.year, now.month, now.day, now.hour, now.minute
minute = str(minute) if minute > 9 else '0' + str(minute)
time = str(year) + '-' + str(month) + '-' + str(day) + ' ' + str(hour) + ':' + minute
with open('data\\' + p.uid, 'w', encoding='UTF-8') as info:
info.write('$SAVE TIME: ' + time + '\n')
info.write(p.classname + '\n')
info.write('#UID#' + p.uid + '\n')
info.write('#NAME#' + p.name + '\n')
info.write('#SEX#' + p.sex + '\n')
info.write('#DESCRIPTION#' + p.description + '\n')
info.write('#OCCUPATION#' + p.occupation + '\n')
info.write('#SIGNATURE#' + p.signature + '\n')
info.write('#BIRTH YEAR#' + str(p.birthYear) + '\n')
info.write('#BIRTH MONTH#' + str(p.birthMonth) + '\n')
info.write('#BIRTH DAY#' + str(p.birthDay) + '\n')
if p.classname == 'WeiboUser':
info.write('#LOCATION#' + p.location + '\n')
info.write('#COMPANY#' + p.company + '\n')
info.write('#IDENTITY#' + p.identity + '\n')
info.write('#CUSTOMED DOMAIN#' + p.customDomain + '\n')
info.write('#FOCUS NUMBER#' + str(p.realFocusNum) + '\n')
info.write('#FANS NUMBER#' + str(p.realFansNum) + '\n')
elif p.classname == 'Person':
info.write('#FOCUS NUMBER#' + str(p.focusNum) + '\n')
info.write('#FANS NUMBER#' + str(p.fansNum) + '\n')
else:
pass
info.write('#FOCUS#')
if (focus := p.focus):
for i in range(len(focus)-1):
info.write(focus[i].uid + ';')
info.write(focus[-1].uid)
info.write('\n')
info.write('#FANS#')
if (fans := p.fans):
for i in range(len(fans)-1):
info.write(fans[i].uid + ';')
info.write(fans[-1].uid)
3. 读取数据
把保存数据的方法反过来,代码:
def load(uid):
filename = 'data\\' + uid
if not os.path.exists(filename):
print('数据不存在')
return False
with open(filename, 'r', encoding='UTF-8') as file:
data = file.readline() # 第一行
print('save time:', data[1:-1])
data = file.readline() # 第二行
p = Person(uid=uid)
if data.strip('\n') == 'WeiboUser':
p = WeiboUser(uid=uid)
else:
raise RuntimeError('Wrong declaration')
while (data := file.readline()):
if data[0] == '#':
section = data[1:].split('#')
propName = section[0]
prop = section[1].strip('\n')
if propName == 'NAME':
p.name = prop
elif propName == 'SEX':
p.sex = prop
elif propName == 'DESCRIPTION':
p.description = prop
elif propName == 'OCCUPATION':
p.occupation = prop
elif propName == 'SIGNATURE':
p.signature = prop
elif propName == 'BIRTH YEAR':
p.birthYear = int(prop)
elif propName == 'BIRTH MONTH':
p.birthMonth = int(prop)
elif propName == 'BIRTH DAY':
p.birthDay = int(prop)
elif propName == 'LOCATION':
p.location = prop
elif propName == 'COMPANY':
p.company = prop
elif propName == 'IDENTITY':
p.identity = prop
elif propName == 'CUSTOMED DOMAIN':
p.customDomain = prop
elif propName == 'FOCUS NUMBER':
if p.classname == 'WeiboUser':
p.realFocusNum = int(prop)
elif propName == 'FANS NUMBER':
if p.classname == 'WeiboUser':
p.realFansNum = int(prop)
elif propName == 'FOCUS':
p.focusList = prop.split(';')
elif propName == 'FANS':
p.fansList = prop.split(';')
else:
pass
return p