用python用正则表达式提取数据



我正在尝试使用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...

最新更新