SpringBoot + Thymeleaf + Bootstrap + 随手记 实现自动记账

前情提要

在用随手记勤勤恳恳记了6年账之后,突然有天开始变懒了。既然每笔消费都从手机上支出,为什么不写个程序来自动完成这个动作呢?

思路

目前日常支出无非两种,一种是支付宝,一种是微信。说到这个,再次吐槽微信支付做的真的是一坨shit。
因为都绑定了信用卡,所以只要是能使用信用卡的地方都优先使用了信用卡来付款,这样的好处,每笔消费记录都以电子账单的形式发送到邮箱。
基于以上,一个自动记账的程序大体思路就浮现了。

第一步 读取邮箱邮件内容,取得招商银行的的账单信息,分析账单得到每笔消费
第二步 获取到"随手记"系统的支出类别的类别编码
第三步 根据消费店铺的收款方和付款时间来识别这笔消费属于什么分类,比如 只要含有地铁或者深圳通 就可以识别为公共交通类的支出
第四步 把识别好的账单记录保存到随手记

实现

本篇博客没想要怎么介绍从头搭建一整套框架,只是想实现一个身边的需求来方便自己,重点是引发各位怎么样去实现自己身边的需求,所以不会介绍怎么从头搭建一套框架。

项目大体分以下7个部分

  1. 搭建后台框架
  2. 设计数据库表
  3. 引入JavaMail 组件 解析邮件内容
  4. 解析并存储邮件里的账单内容
  5. 爬取随手记获得所有类型
  6. 识别账单和随手记中类别的对应关系
  7. 保存到随手记

1.搭建后台框架

在此推荐一个SpringBoot + mybatis 的种子项目
Git地址: https://github.com/lihengming/spring-boot-api-project-seed

2.数据库表设计

  1. 首先我们需要一张邮件email表来记录收到邮件的日期,邮件ID等防止重复读取邮件
  2. 然后我们需要账单流水表account_flow来保存从邮件中解析到的具体消费信息
  3. 保存从随手记上同步到的类型我们需要一张类型ssj_type
  4. 最后我们需要一张relation表,来保存随手记系统中的类型ID和我们的消费店铺关系

以上,总共4张表。

3.引入JavaMail 组件 解析邮件内容

java 使用 JavaMail 组件网络上已经有大量资料,推荐系列文章JavaMail学习笔记

此处有几个要注意的地方

  1. 邮箱必须要开启POP3接受 设置->账户 里面开启
  2. 以QQ邮箱为例默认抓取的是最近30天的邮件,可自行更改

4.解析并存储邮件里的账单内容

为了解析邮件内容,需要引入 jsoup包 Maven坐标如下

   <dependency>
       <groupId>org.jsoup</groupId>
       <artifactId>jsoup</artifactId>
       <version>1.11.3</version>
   </dependency>

参考资料: jsoup中文学习手册
以招商银行账单为例 ,把邮件内容另存为html可以看的如下图。
我们只要解析这个部位的html,拿到表格内容也就得到了具体的消费信息
在这里插入图片描述
右键查看源码,可以看到,每行的内容都在一个id为 fixBand28 的span标记下
在这里插入图片描述
我们可以使用 jsoup 来解析这段html, 关键代码如下

    Document doc = Jsoup.parse("邮件正文");
	Elements spans = doc.select("[id=fixBand28]");
	saveAccountFlow(spans, mailId);

	/**
	 * 保存账务流水
	 * @param spans 招商银行账单表格TD
	 * @param mailId 内容来自的邮件ID
	 */
	private void saveAccountFlow(Elements spans, Integer mailId) {
   
		List<AccountFlow> accountFlowList = new ArrayList<>();
		for (Element span: spans) {
   
			Elements cardNo = span.select("[id=fixBand29]");
			Elements tradeDate = span.select("[id=fixBand30]");
			Elements tradeTime = span.select("[id=fixBand31]");
			Elements currency = span.select("[id=fixBand32]");
			Elements store = span.select("[id=fixBand33]");
			Elements money = span.select("[id=fixBand34]");

			AccountFlow accountFlow = new AccountFlow();
			accountFlow.setEmailId(mailId);
			accountFlow.setCardNo(cardNo.text());
			Date tradeDateTime = turnDateStr(tradeDate.text() +" " +tradeTime.text());
			accountFlow.setTradeDate(tradeDateTime);
			accountFlow.setCurrency(currency.text());
			accountFlow.setStore(store.text());
			accountFlow.setMoney(new BigDecimal(money.text()));
			accountFlowList.add(accountFlow);
		}
		accountFlowService.save(accountFlowList);
	}

至此,已经把账单内容从邮件中提取到了我们自己的数据库中,接下来是使用HttpClient来模拟登录随手记

5.爬取随手记获得所有类型

这部分思路是,打开随手记官网登录 用谷歌浏览器F12获得url,然后用httpclient来模拟登录。

这块遇到的第一个问题,随手记官网登录虽然没有使用验证码机制拦截,但是在传输时是用了JS加密密码。加密的方式是,在页面加载时获得一个vccode+uid 然后在登录时候 要在js里用vccode+密码+帐号 混淆密码后传输。
好消息是在 Java 8 中的Nashorn 引擎实现了用java去执行js脚本,省去了要用java实现一遍js加密逻辑的问题。
在随手记登录界面,右键查看源代码找到
<script type="

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值