首页 文章

使用REGEX阅读财务报表

提问于
浏览
1

我正在开展一个项目,我必须阅读财务报表的扫描图像 . 我使用tesseract 4将图像转换为文本输出,看起来像这样(这里是一个片段):

收入9,000,000 900,000

销售成本900,000 900,000

总利润(90%; 2016年 - 90%)900,000 900,000

我想将上面的内容分成三个条目的列表,其中第一个条目是文本,然后第二个和第三个条目是数字 . 例如,第一行看起来像这样:

[[REVENUE], [9,000,000], [9,000,000]]

我遇到了这个堆栈溢出帖子,有人试图使用 re.match().groups() 方法来查找模式:How to split strings into text and number?

我刚刚介绍正则表达式,我正在努力正确理解语法和文档 . 我现在正在尝试使用备忘单,但我很难搞清楚如何解决这个问题,请帮忙 .

3 回答

  • 0

    我通过观察你的第一个预期输出来写这个正则表达式 . 但我不确定你的第三句话你想要的输出是什么 .

    • ([A-Za-z ]+)(?=\d|\S) 匹配名称,直到找到数字或符号 .

    • .*? 为我们不关心的字符串

    • ([\d,]+)\s([\d,]+|(?=-\n|-$)) 匹配一组或两组数字,如果只有一组数字,则该组应以换行符或文本结尾结束 .

    测试代码(已编辑):

    import re
    
    regex = r"([A-Za-z ]+)(?=\d|\S).*?([\d,]+)\s([\d,]+|(?=-\n|-$))"
    
    text = """
    REVENUE 9,000,000 900,000
    
    COST OF SALES 900,000 900,000
    
    GROSS PROFIT (90%; 2016 - 90%) 900,000 900,000
    
    Business taxes 999 -
    """
    
    print(re.findall(regex,text))
    # [('REVENUE ', '9,000,000', '900,000'), ('COST OF SALES ', '900,000', '900,000'), ('GROSS PROFIT ', '900,000', '900,000'), ('Business taxes ', '999', '')]
    
  • 1

    正如你所说的那样,正则表达式对这个问题有些过分 .

    text.split() 和最后两个之前的项目 join 更适合这个 .

    lines = [ "REVENUE 9,000,000 900,000",
              "COST OF SALES 900,000 900,000",
              "GROSS PROFIT (90%; 2016 - 90%) 900,000 900,000" ]
    out = []
    for line in lines:
        parts = line.split()
        if len(parts) < 3:
            raise InputError
        if len(parts) == 3:
            out.append(parts)
        else:
            out.append([' '.join(parts[0:len(parts)-2]), parts[-2], parts[-1]])
    

    out 将包含

    [['REVENUE', '9,000,000', '900,000'], 
      ['COST OF SALES', '900,000', '900,000'], 
      ['GROSS PROFIT (90%; 2016 - 90%)', '900,000', '900,000']]
    

    如果标签文本需要进一步提取,您可以使用正则表达式,或者您只需查看 parts[0:len(parts)-2] 中的项目并根据那里的单词和数字处理它们 .

  • 1

    检测字符串

    rev_str = "[[REVENUE], [9,000,000], [9,000,000]]"
    

    并提取值

    ("REVENUE", "9,000,000", "9,000,000")
    

    你会的

    import re
    x = re.match(r"\[\[([A-Z]+)\], \[([0-9,]+)\], \[([0-9,]+)\]\]", rev_str)
    x.groups()
    # ('REVENUE', '9,000,000', '9,000,000')
    

    让我们解开这个大字符串 .

    • 方括号表示一系列字符 . 例如, [A-Z] 表示查找 AZ 的所有字母,而 [0-9,] 表示查找数字 09 ,以及字符 , . - 这里是一个在方括号内使用的运算符,表示我们想要的一系列字符 .

    • + 运算符意味着至少查找一次紧接在它之前的任何事件 . 例如,表达式 [A-Z]+ 表示查找任何字母 AZ 中至少出现一次 . 您也可以使用 * 运算符来查找至少为零的事件 .

    • 圆括号(即括号)表示要从正则表达式中提取的组 . 只要匹配该模式,括号中任何表达式内的任何内容都将被提取并作为一组返回 . 例如, ([A-Z+]) 表示查找至少一次出现的任何字母 AZ ,然后保存原来的内容 . 我们在将正则表达式匹配的结果赋给变量 x 之后执行 x.groups() 来访问它 .

    • 否则,它很简单 - 适应模式 [[TEXT], [NUMBER], [NUMBER]] . 方括号使用 \ 字符进行转义,因为我们希望按字面解释它们,而不是作为一系列字符 .

    • 总体而言, re.match() 函数将搜索 rev_str 以查找给定模式匹配的任何位置,跟踪该匹配中的组,并在调用 x.groups() 时返回这些组 .

    这是一个相当简单的例子,但你必须从某个地方开始,对吧?您应该能够将此作为制作更复杂的正则表达式来处理更多代码的起点 .

相关问题