python正则表达式识别案号

python正则表达式识别案号

  • 最近在做信息抽取相关,要从"(2022)鲁1082民初3006号的被告是白振江吗?""(2017)鲁1082执205号案件的执行法院是?" 这些句子中抽取出案号

  • 代码如下

    import re
    class CaseNumberRecognizer:
    
        def __init__(self):
            self.pattern = r"\(\d{4}\)\S+号"
    
        def recognize(self,text):
            result = re.search(self.pattern,text)
            if result:
                return result.group(0)
            else:
                return None
    
    

    测试数据如下(下面是我让chatgpt moke的数据集,不代表任何真实性)

    test_cases = [
        "这是一个案号()号:(2021)鲁1001民初12345号是一起经济纠纷案件",
        "(2022)皖0201民初88888号涉及违反劳动合同纠纷",
        "(2021)豫0716执994号是一起执行案件",
        "**sdua(2022)川2801执301号是一起借款追讨案件",
        "(2021)浙0101民初200号与商业合作有关",
        "(2022)苏0101民初88号是一起房屋买卖纠纷案件",
        "(2022)皖1101执1024号涉及企业合同违约",
        "(2021)鲁0801执10001号是一起债务追偿案件",
        "(2022)浙1001民初500号与商品质量有关",
        "(2021)冀0201民初888号涉及公司股权纠纷",
        "(2022)皖2501执666号是一起强制执行案件",
        "(2021)鄂0201民初33333号是一起离婚案件",
        "(2022)鄂0101执203号涉及公司破产清算",
        "(2021)川0101民初1000号是一起房屋租赁纠纷案件",
        "(2022)苏2501执1024号与违规借款有关",
        "(2021)湘0101执8008号是一起股权纠纷案件",
        "(2022)沪0101民初555号与知识产权有关",
        "(2021)鲁2801民初110号是一起建筑工程施工合同纠纷",
        "(2022)皖1201执1234号是一起执行公证债权文书案件",
        "(2021)粤0101民初9999号是一起侵犯商业秘密纠纷案件",
    ]
    
    for case in test_cases:
        res = recognizer.recognize(case)
        print(res)
    

    识别结果:

    2021)鲁1001民初12345号
    (2022)皖0201民初88888号
    (2021)豫0716994号
    (2022)川2801301号
    (2021)浙0101民初200号
    (2022)苏0101民初88号
    (2022)皖11011024号
    (2021)鲁080110001号
    (2022)浙1001民初500号
    (2021)冀0201民初888号
    (2022)皖2501666号
    (2021)鄂0201民初33333号
    (2022)鄂0101203号
    (2021)川0101民初1000号
    (2022)苏25011024号
    (2021)湘01018008号
    (2022)沪0101民初555号
    (2021)鲁2801民初110号
    (2022)皖12011234号
    (2021)粤0101民初9999
  • 正则表达式解释

    self.pattern = r"\(\d{4}\)\S+号"
    

    匹配以中文左括号、四位数字、中文右括号开始,后面跟着任意非空白字符(1个或多个),最后以中文“号”结束的字符串。

    各个部分的含义如下:

    • \(:匹配中文左括号。
    • \d{4}:匹配四个连续的数字。
    • \):匹配中文右括号。
    • \S+:匹配一个或多个非空白字符。
    • :匹配中文“号”字符
  • 把上面的程序保存为 case_number_recognizer.py

  • 然后让chatgpt帮我写了一个单元测试

    import unittest
    from case_number_recognizer import CaseNumberRecognizer
    
    class TestCaseNumberRecognizer(unittest.TestCase):
        def setUp(self):
            self.recognizer = CaseNumberRecognizer()
    
        def test_recognize_valid_case_number(self):
            text = "这是一个(2021)鲁1001民初12345号的案例"
            expected_result = "(2021)鲁1001民初12345号"
            actual_result = self.recognizer.recognize(text)
            self.assertEqual(actual_result, expected_result)
    
        def test_recognize_invalid_case_number(self):
            text = "这个文本中没有案号"
            expected_result = None
            actual_result = self.recognizer.recognize(text)
            self.assertEqual(actual_result, expected_result)
    
        def test_recognize_multiple_case_numbers(self):
            text = "这个文本中包含多个案号:(2021)鲁1001民初12345号和(2022)皖0201民初88888号"
            expected_result = "(2021)鲁1001民初12345号"
            actual_result = self.recognizer.recognize(text)
            self.assertEqual(actual_result, expected_result)
    
    if __name__ == '__main__':
        unittest.main()
    

    这是一个Python的单元测试代码,用于测试一个名为CaseNumberRecognizer的案号识别器的三个方法。
    首先,导入了unittest模块,并导入了要测试的CaseNumberRecognizer类。在测试中,定义了一个TestCaseNumberRecognizer的子类,其中包含三个测试方法:

    1. test_recognize_valid_case_number(),用于测试识别一个有效的案号;
    2. test_recognize_invalid_case_number(),用于测试识别一个无效的案号;
    3. test_recognize_multiple_case_numbers(),用于测试识别多个案号时的情况。
      在setUp()方法中,实例化了CaseNumberRecognizer类,用于在每个测试方法中使用相同的对象。
      在每个测试方法中,定义了要测试的输入文本和预期结果,然后调用CaseNumberRecognizer类的recognize方法,获得实际结果。接着使用self.assertEqual()断言函数,将实际结果和预期结果进行比较。如果测试结果和预期结果相同,则测试通过,否则测试失败。
      最后,在__name__ == 'main’条件成立时,执行unittest.main()函数,运行所有测试用例。

    结果如下

    ======================================================================
    FAIL: test_recognize_multiple_case_numbers (__main__.TestCaseNumberRecognizer)
    ----------------------------------------------------------------------
    
    AssertionError: '(2021)鲁1001民初12345号和(2022)皖0201民初88888号' != '(2021)鲁1001民初12345号'     
    -2021)鲁1001民初12345号和(2022)皖0201民初88888+2021)鲁1001民初12345----------------------------------------------------------------------
    Ran 3 tests in 0.001s
    
    FAILED (failures=1)
    
  • 修改代码

    import re
    
    class CaseNumberRecognizer:
    
        def __init__(self):
            self.pattern = r"(\d{4})\S+?号"
    
        def recognize(self, text):
            results = re.findall(self.pattern, text)
            if results:
                return [result for result in results]
            else:
                return None
    
    for text in test_cases:
        recognizer = CaseNumberRecognizer()
        result = recognizer.recognize(text)
        print(f"识别结果为“{result}”")
    

    识别结果为“['(2021)鲁1001民初12345号', '(2022)皖0201民初88888号']”

    • 那么这个正则表达式

      这个正则表达式的结构如下:

      1. :匹配一个全角左括号。
      2. \d{4}:匹配四个连续的数字字符,如 “2021”。
      3. :匹配一个全角右括号。
      4. \S+?:匹配任意非空白字符(\S)一次或多次(+),但尽可能少匹配(?)。因为 ? 是紧跟在 + 后面的,所以它改变了 + 的贪婪性质,使其尽可能少地匹配字符。
      5. :匹配一个中文字符 “号”。

      这个正则表达式的目的是从文本中提取符合案号格式的字符串。案号格式通常以一个全角括号内的四位数字年份开始,然后是一系列非空白字符,最后以中文字符 “号” 结尾。加入 ? 的原因是为了在文本中正确分离多个案号。

    • 和前面那个区别在哪

      原因在于正则表达式的贪婪性质。在这个例子中,关键的区别在于 ++?

      在第一个正则表达式 r"(\d{4})\S+?号" 中,+? 是非贪婪匹配,即在满足整个模式的前提下尽可能少地匹配字符。这意味着它会在遇到第一个满足条件的 “号” 时停止匹配,从而正确地分割出多个案号。

      而在第二个正则表达式 r"\(\d{4}\)\S+号" 中,+ 是贪婪匹配,即在满足整个模式的前提下尽可能多地匹配字符。这意味着它会一直匹配到最后一个满足条件的 “号”,导致多个案号被当作一个完整的匹配结果。

      因此,在这个例子中,将贪婪匹配 + 改为非贪婪匹配 +? 可以正确地分割出文本中的多个案号。

  • 案号还有别的情况

    • 有的是英文括号,还有的是这种格式:第10979500号
    import re
    
    class CaseNumberRecognizer:
    
        def __init__(self):
            self.pattern = r"[((]\d{4}[))]\S+\d+号|第\d+号"
    
        def recognize(self, text):
            results = re.findall(self.pattern, text)
            if results:
                return [result for result in results]
            else:
                return None
    
    text = "(2017)鲁1082执205号 和 (2019)鲁1002民初1379号 以及 (2022)闽民终1061号 和 第10979500号 和 第8911270号 和 (2021)粤0106执异153号"
    recognizer = CaseNumberRecognizer()
    results = recognizer.recognize(text)
    if results:
        for result in results:
            print(result)
    else:
        print("未识别到任何案号")
    

    识别结果

    2017)鲁1082205号
    (2019)鲁1002民初1379(2022)闽民终1061号
    第10979500号
    第8911270(2021)0106执异153

    解释

    这个正则表达式包含两部分,用 | 分隔,表示匹配左边或右边的表达式。

    1. [((]\d{4}[))]\S+\d+号:这部分的正则表达式用于匹配大部分情况下的案号。
      • [((]:匹配中文括号 “(” 或英文括号 “(”。[...] 表示字符集,匹配其中任意一个字符。

      • \d{4}:匹配四位数字。\d 表示数字,{4} 表示匹配前面的元素四次。

      • [))]:匹配中文括号 “)” 或英文括号 “)”。与 [((] 类似,这里也是匹配其中任意一个字符。

        在正则表达式中,[...]
        表示字符集,它的作用是匹配其中任意一个字符。在本例中,[))]
        的作用是匹配中文括号 “)” 或英文括号 “)”。这样做的目的是让正则表达式能够同时处理中文括号和英文括号的情况,增加匹配的灵活性。

      • \S+:匹配任意非空白字符一次或多次。\S 表示非空白字符,+ 表示匹配前面的元素一次或多次。

      • \d+:匹配数字一次或多次。\d 表示数字,+ 表示匹配前面的元素一次或多次。

      • :匹配中文字符 “号”。

    • 第\d+号:这部分的正则表达式用于匹配极少数情况下的案号。
      • :匹配中文字符 “第”。
      • \d+:匹配数字一次或多次。\d 表示数字,+ 表示匹配前面的元素一次或多次。
      • :匹配中文字符 “号”。

    总结:这个正则表达式主要匹配两种类型的案号,一种是大部分情况下的案号,格式为:括号(中文或英文)+ 年份 + 省份简称 + 数字 + 表示案件性质、状态的词 + 数字 + 号;另一种是极少数情况下的案号,格式为:第 + 数字 + 号。使用 | 将这两种匹配条件连接起来,表示只要满足其中任意一种条件即可匹配。

你可能感兴趣的:(python相关,python,正则表达式)