翼度科技»论坛 编程开发 python 查看内容

【pyhon笔记】钱迹x信用卡辅助对账(个人用)

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
背景

记账强迫症患者,苦于账本上的信用卡额度总跟实际的对不上,python小白的我决定写个小demo辅助对账。
涉及


  • python  BeautifulSoup
  • SQLite
准备


  • 信用卡账单eml(这里用的J行)
  • 钱迹账单csv
关键步骤

解析并处理信用卡账单

使用BeautifulSoup组件,解析账单eml
  1.     # 读取账单eml
  2.     eml = open(source_path).read()
  3.     # 使用Parser解析eml
  4.     content = Parser().parsestr(eml)
  5.     bill = ""
  6.     # 深度优先遍历
  7.     for par in content.walk():
  8.         # 消息的有效内容是一个子EmailMessage对象的列表,则返回True,否则返回False
  9.         if not par.is_multipart():
  10.             content = par.get_payload(decode=True)
  11.             if len(content.strip()) != 0:
  12.                 # 这里,会得到唯一的一个包含账单的html字符串
  13.                 bill = content.decode(encoding='gbk')
  14.     # 这里需要重点注意
  15.     # 使用BeautifulSoup转化前,需要事先将换行符去掉
  16.     # 否则,带有换行符节点的标签对象会解析不出来,直接变成None
  17.     data = BeautifulSoup(bill.replace('
  18. ', '').replace('<br/>', ''), "html.parser")
复制代码
搜索账单列表。通过分析账单,还款明细的开头如下所示是一个id为takeList的tbody
  1. [/code]然后,这个tbody还会包含一个唯一的tbody,这个tbody下面就是一条一条的还款明细了
  2. [code]# 得到还款明细列表
  3. repayList = data.find("tbody", id="repayList").find("tbody")
复制代码
同理,也能得到消费列表
  1. takeList = data.find("tbody", id="takeList").find("tbody")
复制代码
逐条解析消费明细,得到交易列表
  1.     bills = []
  2.     repayAmount = Decimal(0.00)
  3.     for repay in repayList.children:
  4.         # NavigableString类型,就是没有子节点的字符串
  5.         # BeautifulSoup会将注释也解析进去,主要就是为了排除注释
  6.         if not isinstance(repay, NavigableString):
  7.             bill = {}
  8.             bill["type"] = "repay"
  9.             for item in repay.children:
  10.                 # 匹配日期 MM/dd
  11.                 if re.match("\d\d/\d\d", str(item.string), flags=0):
  12.                     bill["time"] = year + "-" + str(item.string).replace("/", "-")
  13.                 # 匹配金额
  14.                 elif re.match("CNY\d*\.\d*", str(item.string), flags=0):
  15.                     amount = str(item.string)[3:]
  16.                     bill["amount"] = amount
  17.                     repayAmount += Decimal(float(amount))
  18.             bills.append(bill)
复制代码
为了之后方面对账,就将上面的数据处理成了如下所示格式
  1. {
  2.     "month": "2023-02",
  3.     "name": "信用卡08月",
  4.     "bills": {
  5.         "2022-02-22": [{
  6.             "type": "repay",
  7.             "channel": "BCM",
  8.             "time": "2022-02-22",
  9.             "amount": "2.00"
  10.         }]
  11.     },
  12.     "size": 1,
  13.     "start": "17"
  14. }
复制代码
处理钱迹账单

导入SQLite

为了方便搜索数据,我用钱迹账单csv生成了SQLite数据库文件
搜索钱迹数据
  1.     current = current + relativedelta(days=1)
  2.     endtime = current.strftime("%Y-%m-%d") + " 00:00:00"
  3.     conn = sqlite3.connect(db_dir)
  4.     cur = conn.cursor()      
  5.     cur.execute("select *from qian_ji qj where 时间 >= '" + starttime + "' and 时间 < '" + endtime + "' and 账户1 ='" + 账户名称 + "'")
复制代码
比对数据

因为信用卡的账单是一个月一个,所以我这边也是一次比对一个月。
从账单日第一天开始,一直到下个月的账单日前一天,逐日分别计算当天信用卡和钱迹的交易净值并比对
感想

算是花了不少时间,实际最后也没做出啥像样的东西,但至少整个过程下来,也是学到了不少东西。
至少,目的达成了————成功阻止了我自己手动去改账本上的账户金额。
后续再继续研究下其他渠道的账单。

来源:https://www.cnblogs.com/yiusnow/p/17179108.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具