我正在尝试使用python从txt文件中提取数据(参见下面的示例文本)。考虑到标题可以在一行中,也可以分成两行,甚至可以在中间分割空白行(TITLE1)。
我想要实现的是提取信息以存储在表中,如下所示:
<表类>
代码
标题
开放日期
期限
预算
title - sdfsd - dfds - sfds -01-01
这是标题1,分为两行,中间有一个空白行
15-Apr-21
26-Aug-21
EUR 2000万
TITLE-SDFSD-DFDS-SFDS-01-02
这是标题2在一个单行
21年3月15日
21年8月17日
€1500万
TITLE-SDFSD-DFDS-SFDS-01-03
这是标题3太长,占用了两行
15-May-21
26-Sep-21
€500万
表类>
对捕获组使用正则表达式。使用re.DOTALL
标志允许.*
跨多行匹配,这样您就可以捕获多行标题。并且使用惰性量词来避免匹配太长。
import csv
import re
pattern = re.compile(r'^(TITLE-.+?-d{2}-d{2})S*s*(.*?)^Conditions.*?^Opening date (d{1,2} w+ d{4})s*?^Deadline (d{1,2} w+ d{4})s*^Indicative budget:.*?(EUR [d.]+ w+)', re.MULTILINE | re.DOTALL)
matches = pattern.finditer(f_contents)
with open("result.csv", "w") as outfile:
csvfile = csv.writer(outfile)
csvfile.writerow(['Code', 'Title', 'Opening date', 'Deadline', 'Budget'])
for match in matches:
csvfile.writerow([match.group(1), match.group(2).replace('n', ' '), match.group(3), match.group(4), match.group(5)])
演示您可以使用捕获组获得匹配项。
注意可以将(?!,)S
写成[^s,]
根据示例中的行:
^(TITLE-.+?-[0-9]{2}-[0-9]{2})[^s,] (.*(?:r?n(?![A-Z]).*)*)(?:r?n(?!Opening).*)*r?nOpening date (d+ .*)(?:r?n(?!Deadline).*)*r?nDeadline (d+ .*)(?:r?n(?!Indicative budget:).*)*r?nIndicative budget: .*?(EUR d+(?:.d+)? w+)
解释
^
字符串 起始(TITLE-.+?-[0-9]{2}-[0-9]{2})
Capture组1,匹配标题部分[^s,]
匹配除逗号以外的任何非空白字符(.*(?:r?n(?![A-Z]).*)*)
Capture组2,匹配所有不以大写字符 开头的行。(?:r?n(?!Opening).*)*r?nOpening date
匹配到起始日期(d+ .*)
Capture组3,匹配1+数字,空格和行 的其余部分。(?:r?n(?!Deadline).*)*r?nDeadline
匹配所有行直到截止日期(d+ .*)
Capture第4组,匹配1+数字和行 的其余部分(?:r?n(?!Indicative budget:).*)*r?nIndicative budget: .*?
匹配所有行直到指示性预算:(EUR d+(?:.d+)? w+)
Capture第5组,匹配EUR、数字和1+字字符
Regex demo | Python demo
然后你可以将它加载到表或数据框中
with open('doubt2.txt','r', encoding="utf-8") as f:
f_contents = f.read()
pattern = re.compile(r"^(TITLE-.+?-[0-9]{2}-[0-9]{2})[^s,] (.*(?:r?n(?![A-Z]).*)*)(?:r?n(?!Opening).*)*r?nOpening date (d+ .*)(?:r?n(?!Deadline).*)*r?nDeadline (d+ .*)(?:r?n(?!Indicative budget:).*)*r?nIndicative budget: .*?(EUR d+(?:.d+)? w+)", re.MULTILINE)
matches = pattern.findall(f_contents)
df = pd.DataFrame(matches, columns = ['Code', 'Title', 'Opening date', 'Deadline', 'Budget'])
df['Title'] = df['Title'].str.replace('[rn]+',' ')
print(df)
输出
Code Title Opening date Deadline Budget
0 TITLE-SDFS... This is th... 15 Apr 2021 26 Aug 2021 EUR 20.00 ...
1 TITLE-SDFS... This is th... 15 March 2021 17 Aug 2021 EUR 15.00 ...
2 TITLE-SDFS... This is th... 15 May 2021 26 Sep 2021 EUR 5.00 m...