最近在做信息抽取相关,要从"(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)豫0716执994号
(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号
正则表达式解释
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的子类,其中包含三个测试方法:
结果如下
======================================================================
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号']”
那么这个正则表达式
这个正则表达式的结构如下:
(
:匹配一个全角左括号。\d{4}
:匹配四个连续的数字字符,如 “2021”。)
:匹配一个全角右括号。\S+?
:匹配任意非空白字符(\S
)一次或多次(+
),但尽可能少匹配(?
)。因为 ?
是紧跟在 +
后面的,所以它改变了 +
的贪婪性质,使其尽可能少地匹配字符。号
:匹配一个中文字符 “号”。这个正则表达式的目的是从文本中提取符合案号格式的字符串。案号格式通常以一个全角括号内的四位数字年份开始,然后是一系列非空白字符,最后以中文字符 “号” 结尾。加入 ?
的原因是为了在文本中正确分离多个案号。
和前面那个区别在哪
原因在于正则表达式的贪婪性质。在这个例子中,关键的区别在于 +
与 +?
。
在第一个正则表达式 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)鲁1082执205号
(2019)鲁1002民初1379号
(2022)闽民终1061号
第10979500号
第8911270号
(2021)粤0106执异153号
解释
这个正则表达式包含两部分,用 |
分隔,表示匹配左边或右边的表达式。
[((]\d{4}[))]\S+\d+号
:这部分的正则表达式用于匹配大部分情况下的案号。
[((]
:匹配中文括号 “(” 或英文括号 “(”。[...]
表示字符集,匹配其中任意一个字符。
\d{4}
:匹配四位数字。\d
表示数字,{4}
表示匹配前面的元素四次。
[))]
:匹配中文括号 “)” 或英文括号 “)”。与 [((]
类似,这里也是匹配其中任意一个字符。
在正则表达式中,
[...]
表示字符集,它的作用是匹配其中任意一个字符。在本例中,[))]
的作用是匹配中文括号 “)” 或英文括号 “)”。这样做的目的是让正则表达式能够同时处理中文括号和英文括号的情况,增加匹配的灵活性。
\S+
:匹配任意非空白字符一次或多次。\S
表示非空白字符,+
表示匹配前面的元素一次或多次。
\d+
:匹配数字一次或多次。\d
表示数字,+
表示匹配前面的元素一次或多次。
号
:匹配中文字符 “号”。
第\d+号
:这部分的正则表达式用于匹配极少数情况下的案号。
第
:匹配中文字符 “第”。\d+
:匹配数字一次或多次。\d
表示数字,+
表示匹配前面的元素一次或多次。号
:匹配中文字符 “号”。总结:这个正则表达式主要匹配两种类型的案号,一种是大部分情况下的案号,格式为:括号(中文或英文)+ 年份 + 省份简称 + 数字 + 表示案件性质、状态的词 + 数字 + 号;另一种是极少数情况下的案号,格式为:第 + 数字 + 号。使用 |
将这两种匹配条件连接起来,表示只要满足其中任意一种条件即可匹配。