草庐IT

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

漪雪 2023-03-28 原文

背景

记账强迫症患者,苦于账本上的信用卡额度总跟实际的对不上,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 ='" + 账户名称 + "'")
比对数据

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

感想

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

有关【pyhon笔记】钱迹x信用卡辅助对账(个人用)的更多相关文章

  1. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  2. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  3. ruby-on-rails - Controller 中的 Rails 辅助模块 - 2

    我有一个Controller,我想为这个Controller创建一个助手,我可以在不包含它的情况下使用它。我尝试像这样创建一个与Controller同名的助手classCars::EnginesController我创建的助手是moduleCars::EnginesHelperdefcheck_fuellogger.debug("chekingfuel")endend我得到的错误是undefinedlocalvariableormethod`check_fuel'for#有没有我遗漏的约定? 最佳答案 如果你真的想在Controll

  4. ruby-on-rails - 为什么 Rails 使用像 link_to 这样的辅助方法而不是 <a href...>? - 2

    我正在学习Rails,我注意到Rails不断地使用诸如link_to之类的辅助方法,而不是仅仅使用普通的html。现在我可以理解为什么他们会使用他们会使用一些辅助方法,但我不明白为什么他们更喜欢辅助方法而不是直接编码html。为什么Rails更喜欢辅助方法而不是您必须手动编写html?为什么Rails团队做出这样的设计选择? 最佳答案 在Rails应用程序中,通常使用URL方法和内容方法生成链接,例如这绝对比将它们放入中更易于管理手动标记。">(您正在使用路由器生成这些URL,对吗?如果您硬编码/users/1并决定稍后将其设为/u

  5. Unity Shader 学习笔记(5)Shader变体、Shader属性定义技巧、自定义材质面板 - 2

    写在之前Shader变体、Shader属性定义技巧、自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用,方便后续回顾查看,如有以偏概全、不祥不尽之处,还望海涵。1、Shader变体先看一段代码......Properties{ [KeywordEnum(on,off)]USL_USE_COL("IsUseColorMixTex?",int)=0 [Toggle(IS_RED_ON)]_IsRed("IsRed?",int)=0}......//中间省略,后续会有完整代码 #pragmamulti_c

  6. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  7. 计算机网络笔记:TCP三次握手和四次挥手过程 - 2

    TCP是面向连接的协议,连接的建立和释放是每一次面向连接的通信中必不可少的过程。TCP连接的管理就是使连接的建立和释放都能正常地进行。三次握手TCP连接的建立—三次握手建立TCP连接①若主机A中运行了一个客户进程,当它需要主机B的服务时,就发起TCP连接请求,并在所发送的分段中用SYN=1表示连接请求,并产生一个随机发送序号x,如果连接成功,A将以x作为其发送序号的初始值:seq=x。主机B收到A的连接请求报文,就完成了第一次握手。客户端发送SYN=1表示连接请求客户端发送一个随机发送序号x,如果连接成功,A将以x作为其发送序号的初始值:seq=x②主机B如果同意建立连接,则向主机A发送确认报

  8. ruby-on-rails - 如何显示信用卡的月份和年份选择 - 2

    我正在使用Rails3.1。这是我的代码,要求用户输入信用卡到期月份和年份。以上代码有效。但是,问题是如果出现验证错误,则会重置所选的到期时间和月份。我试过f.select_month但不支持。 最佳答案 尝试这样的事情:true,:start_year=>Date.today.year,:end_year=>(Date.today.year+10),:use_month_numbers=>true%> 关于ruby-on-rails-如何显示信用卡的月份和年份选择,我们在StackOv

  9. 华为数通笔记VXLAN&BGP EVPN - 2

    VXLAN简介定义RFC定义了VLAN扩展方案VXLAN(VirtualeXtensibleLocalAreaNetwork,虚拟扩展局域网)。VXLAN采用MACinUDP(UserDatagramProtocol)封装方式,是NVO3(NetworkVirtualizationoverLayer3)中的一种网络虚拟化技术。目的随着网络技术的发展,云计算凭借其在系统利用率高、人力/管理成本低、灵活性/可扩展性强等方面表现出的优势,已经成为目前企业IT建设的新趋势。而服务器虚拟化作为云计算的核心技术之一,得到了越来越多的应用。服务器虚拟化技术的广泛部署,极大地增加了数据中心的计算密度;同时,为

  10. ruby-on-rails - 从 Virtus.model 动态扩展时使用 boolean 属性辅助方法 - 2

    假设我有一个带有boolean属性active的Virtus模型User:classUserincludeVirtus.modelattribute:active,Boolean,default:false,lazy:trueend然后我可以使用辅助方法active?:User.new.active?#=>falseUser.new(active:true).active?#=>true但是当我尝试从Virtus.model中扩展并动态定义一个boolean属性时:classUser;enduser=User.newuser.extend(Virtus.model)user.attri

随机推荐