VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > python入门教程 >
  • 【pyhon笔记】钱迹x信用卡辅助对账(个人用)

背景

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

涉及

  • python BeautifulSoup
  • SQLite

准备

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

关键步骤

解析并处理信用卡账单

使用BeautifulSoup组件,解析账单eml
    # 读取账单eml
    eml = open(source_path).read()
    # 使用Parser解析eml
    content = Parser().parsestr(eml)
    bill = ""
    # 深度优先遍历
    for par in content.walk():
        # 消息的有效内容是一个子EmailMessage对象的列表,则返回True,否则返回False
        if not par.is_multipart():
            content = par.get_payload(decode=True)
            if len(content.strip()) != 0:
                # 这里,会得到唯一的一个包含账单的html字符串
                bill = content.decode(encoding='gbk')
    # 这里需要重点注意
    # 使用BeautifulSoup转化前,需要事先将换行符去掉
    # 否则,带有换行符节点的标签对象会解析不出来,直接变成None
    data = BeautifulSoup(bill.replace('<br>', '').replace('<br/>', ''), "html.parser")
搜索账单列表。通过分析账单,还款明细的开头如下所示是一个id为takeList的tbody
<tbody id=takeList>

然后,这个tbody还会包含一个唯一的tbody,这个tbody下面就是一条一条的还款明细了

# 得到还款明细列表
repayList = data.find("tbody", id="repayList").find("tbody")

同理,也能得到消费列表

takeList = data.find("tbody", id="takeList").find("tbody")
逐条解析消费明细,得到交易列表
    bills = []
    repayAmount = Decimal(0.00)
    for repay in repayList.children:
        # NavigableString类型,就是没有子节点的字符串
        # BeautifulSoup会将注释也解析进去,主要就是为了排除注释
        if not isinstance(repay, NavigableString):
            bill = {}
            bill["type"] = "repay"
            for item in repay.children:
                # 匹配日期 MM/dd
                if re.match("\d\d/\d\d", str(item.string), flags=0):
                    bill["time"] = year + "-" + str(item.string).replace("/", "-")
                # 匹配金额
                elif re.match("CNY\d*\.\d*", str(item.string), flags=0):
                    amount = str(item.string)[3:]
                    bill["amount"] = amount
                    repayAmount += Decimal(float(amount))
            bills.append(bill)

为了之后方面对账,就将上面的数据处理成了如下所示格式

{
    "month": "2023-02",
    "name": "信用卡08月",
    "bills": {
        "2022-02-22": [{
            "type": "repay",
            "channel": "BCM",
            "time": "2022-02-22",
            "amount": "2.00"
        }]
    },
    "size": 1,
    "start": "17"
}

处理钱迹账单

导入SQLite

为了方便搜索数据,我用钱迹账单csv生成了SQLite数据库文件

搜索钱迹数据
    current = current + relativedelta(days=1)
    endtime = current.strftime("%Y-%m-%d") + " 00:00:00"
    conn = sqlite3.connect(db_dir)
    cur = conn.cursor()      
    cur.execute("select *from qian_ji qj where 时间 >= '" + starttime + "' and 时间 < '" + endtime + "' and 账户1 ='" + 账户名称 + "'")
比对数据

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

感想

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

出处:https://www.cnblogs.com/yiusnow/p/17179108.html


相关教程