python进行高效记账的小工具
现有记账工具梳理自己开发记账工具的思路记账工具代码简介1.建立3个数据库2.与数据库的交互3.提取数据4.添加交易对象5.生成财务报表5.1高频交易对象及金额报表5.2交易金额排名前20对象报表代码
5.3按分类支出报表代码
后续计划
现有记账工具梳理
对比随手记微信记账优势功能强大、报表丰富自动记账劣势全手工录入、耗费时间,难以坚持;理财产品暴雷😓私人订制功能少、无法自己定义类别、报表简单
那么有没有一款能结合两款产品优势的记账产品呢? 为此我尝试着自己做了一个
自己开发记账工具的思路
需求:
不能接受纯手动输入能够有详细、可订制的分类数据安全
开发思路:
微信支付的帐单批量下载;通过python 、pandas将账单汇总;对高频交易对象分类,将80%的交易按照对象自动分类;设置金阈值,超过阈值8%的交易,手工分类备注;利用pyechart 生成报表。
记账工具代码简介
1.建立3个数据库
数据库暂时先以csv格式保存,计划迭代后用mysql等专业数据库保存 数据读取时以dataframe的形式。
main_data
交易流水的主数据库index 为交易时间(微信支付时间戳最小单位为s)columns:[‘交易对方’,‘收/支’, ‘金额(元)’, ‘支付方式’, ‘当前状态’,‘in_out_NO’] trader_df
交易对方 数据库(微信导出时将交易对象命名为“交易对方”,就不改了)columns:[“交易对方”,“type01_num”] type01_df
管理支出分类columns:[“type_01_num”,“type_01”]暂时只开发了一级分类,后期会根据需求增加二级分类该分类与 trader_df 绑定,每一个高频交易对象都会要求指定一个类别,这样就不用对每笔支出进行分类了。超过一定额度的交易,会强制要求进行再次确认,类似于你与食堂有一笔300元的交易,那么并不会自动归类为吃饭,还是会与你再次确认,是不是属于其他类别(人情往来等) 收入_df (待开发) 预算_df (待开发)
2.与数据库的交互
#建立basic——df的类
class Basic_Df():
def __init__(self):
self.path=[
'basic_data/main_data.csv',
'basic_data/trader_df.csv',
'basic_data/type01_df.csv'
]
self.info='basic_df记录了是与基础数据调用的库'
#导出数据
def output_df(self,df_num):
path=self.path[df_num]
the_df=pd.read_csv(path,index_col=0)
return the_df
#导入数据
def input_df(self,df_num,new_df):
path=self.path[df_num]
new_df.to_csv(path)
return
3.提取数据
微信支付数据提取
如上微信提取的为csv格式 提取csv格式数据
# 新增交易记录到main_data.csv
def get_data(path):
"""get data from path ,then put into main_data.csv
Args:
path (str): the path of add_data.csv
"""
#导入新数据
new_data=pd.read_csv(path,delimiter=",",skiprows=16,index_col=0)
#去掉金额列的 ¥金额 str格式转 float
new_data['金额(元)']=(new_data['金额(元)']
.str.replace('¥','')
.astype('float'))
#将交易对方 里的 “/”替换为 “ 微信红包退款 ”
new_data.loc[new_data['交易对方']=='/','交易对方']='微信红包退款'
new_data['in_out_NO']=1.0
new_data.loc[new_data['收/支']=='收入','in_out_NO']=-1.0
new_data.loc[new_data['收/支']=='支出','in_out_NO']=1.0
new_data['金额(元)']=new_data['金额(元)']*new_data['in_out_NO']
#对导入数据简单处理
col_list=['交易对方','收/支', '金额(元)', '支付方式', '当前状态','in_out_NO']
add_data=new_data[col_list]
# add_data['交易时间']=list(add_data.index)
#与main_data 校对,提取新增数据new_data
main_path='basic_data/main_data.csv'
if os.path.isfile(main_path):
l_data=pd.read_csv(main_path,index_col=0)
l_data=pd.concat([l_data,add_data])
l_data.drop_duplicates(keep='last',inplace=True)
main_data=l_data.to_csv(main_path,index=True)
else:
main_data=add_data.to_csv(main_path,index=True)
#将new_data导入main-data中
return
4.添加交易对象
该方法主要为更新交易对象数据 trader_df
```python
# 添加新的交易对象
def get_new_trader(add_df):
# 提取交易对象频率前20
top_trader=add_df.value_counts('交易对方')
top_trader=top_trader[top_trader>4]
# 录入trader_df
trader_df=Basic_Df()
trader_df=trader_df.output_df(1)
trader_list=trader_df['交易对方'].tolist()
add_trader=top_trader[~top_trader.index.isin(trader_list)].index
trader_num_list=[]
for trader in add_trader:
new_no=13
print('请输入')
print(trader)
new_no=input()
trader_num_list.append(new_no)
add_trader_df=pd.DataFrame()
add_trader_df['交易对方']=add_trader
add_trader_df['type_01_num']=trader_num_list
return add_trader_df
5.生成财务报表
需要引用
# 生成图表需要用到的模块
import pandas as pd
from pyecharts.charts import Bar,Line,Grid,Pie
from pyecharts import options as opts
from pyecharts.globals import ThemeType
from data_wechat import Basic_Df
5.1高频交易对象及金额报表
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401101128368.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0JpbGxpb25Qb255,size_16,color_FFFFFF,t_70#pic_center)
# 生成视图 of 交易频率前20的交易对象及对比
def show_top20_trade_valuse():
"""creat the view of top 20 traders'cost
Args:
main_data (df): main_data.csv
"""
ss_df=Basic_Df()
main_data=ss_df.output_df(0)
#确认交易频率最高的对象
closest_trader=(main_data['交易对方'].value_counts()
.sort_values(ascending=False)
.index[:20]
.tolist()
)
df=(
main_data.groupby(main_data['交易对方'])
.sum()
.loc[closest_trader]
.round(2)
)
counts_list=(main_data['交易对方'].value_counts()
.values[:20]
)
y_list=df['金额(元)']
x_list=df.index
# 生成图像
bar = (
Bar(init_opts=opts.InitOpts(theme=ThemeType.SHINE,height='600px'))
.add_xaxis(x_list.tolist())
.add_yaxis("交易金额",y_list.tolist(),label_opts=opts.LabelOpts(position="top"))
.extend_axis(
yaxis=opts.AxisOpts(
name="频次",
is_inverse=True,
axislabel_opts=opts.LabelOpts(formatter="{value} times"),
axistick_opts=opts.AxisTickOpts(is_show=True),
splitline_opts=opts.SplitLineOpts(is_show=True),
)
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="频次最高20个对象及交易总额", subtitle="微信记账小插件"),
yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value} RMB")),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-30)),
#toolbox_opts=opts.ToolboxOpts(), )
)
line=(
Line()
.add_xaxis(x_list.tolist())
.add_yaxis(
"交易频次",
y_axis=counts_list.tolist(),
yaxis_index=1,
)
)
bar.overlap(line)
bar.render('report/消费频率最高的20个交易对象频次及交易总额.html')
return
5.2交易金额排名前20对象报表
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401101144907.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0JpbGxpb25Qb255,size_16,color_FFFFFF,t_70#pic_center)
代码
# 生成视图 of 交易金额排名最高20位对象
def show_cost_top20_trade():
"""creat the view of top20 trader's cost()
Args:
main_data (df): main_data
"""
ss_df=Basic_Df()
main_data=ss_df.output_df(0)
#确认交易频率最高的对象
closest_trader=(main_data.groupby('交易对方').sum()
.sort_values(by='金额(元)',ascending=False)
.index[:20]
.tolist()
)
df=(
main_data.groupby(main_data['交易对方'])
.sum()
.loc[closest_trader]
.round(2)
)
counts_list=(main_data['交易对方'].value_counts()
.values[:20]
)
y_list=df['金额(元)']
x_list=df.index
# 生成图像
bar = (
Bar(init_opts=opts.InitOpts(theme=ThemeType.PURPLE_PASSION,width='1200px'))
.add_xaxis(x_list.tolist())
.add_yaxis("交易金额",y_list.tolist(),label_opts=opts.LabelOpts(position="right"),)
.reversal_axis()
.set_global_opts(
title_opts=opts.TitleOpts(title="交易金额最高的20名对象", subtitle="Pony's Acount Book"),
datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")],
yaxis_opts=opts.AxisOpts(axislabel_opts={"interval":"0","rotate":30}
)
)
)
bar.render('report/消费top20的交易对象.html')
return
5.3按分类支出报表
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401101153376.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0JpbGxpb25Qb255,size_16,color_FFFFFF,t_70#pic_center)
代码
# 生成按支出分类的视图
def show_top_20_trade():
"""creat the Pie view of pie in type01
Args:
main_data (df): main_data
"""
#模拟新导入的信息main——df
ss_df=Basic_Df()
main_df=ss_df.output_df(0)
type01_df=ss_df.output_df(2)
trader_df=ss_df.output_df(1)
#联合3个基础表
mid_df=pd.merge(main_df,trader_df,how='left')
conf_index=mid_df[mid_df['type_01_num_conf']!=100].index
mid_df.loc[conf_index,'type_01_num']=mid_df.loc[conf_index,'type_01_num_conf']
mid_df=mid_df.fillna({'type_01_num':13})
mid_df['type_01_num']=mid_df['type_01_num'].apply(int)
big_df=pd.merge(mid_df,type01_df,how='left')
#将已经经过conf的typer加入typ——01中
df3=(big_df.loc[~big_df['当前状态'].str.contains('退款',na=False)]
.groupby(big_df['type_01'])
.sum()
)['金额(元)']
#系列数据设置
y_list=df3.values
x_list=df3.index
# 生成图像
pie =(
Pie(init_opts=opts.InitOpts(theme=ThemeType.WONDERLAND))
.add(
series_name='',
data_pair=[k for k in zip(x_list,y_list)])
.set_global_opts(
title_opts=opts.TitleOpts(title="按分类各项支出占比", subtitle="Pony's Acount Book")
)
)
pie.render('report/pay in type.html')
后续计划
开发更多的视图模版开发预算模块开发月度、年度报表开发定期自动推送工具(推送到邮箱、微信等)将数据保存由csv转为mysql等专业数据库导入支付宝数据
|