从文本文件中提取文本块的正则表达式?

3
我需要使用正则表达式在Python中从文本文件中提取标题和其下的文本块,但我发现很难做到。
我将这个PDF转换成了文本,现在看起来像这样: img 到目前为止,我已经能够使用以下正则表达式获取所有数字标题(12.4.5.4, 12.4.5.6, 13, 13.1, 13.1.1, 13.1.12):
import re

with open('data/single.txt', encoding='UTF-8') as file:

    for line in file:
        headings = re.findall(r'^\d+(?:\.\d+)*\.?', line)
        print(headings)`

我只是不知道如何获取标题中的文字部分或者它们下面的段落文本。
编辑 - 这里是文本:
I.S. EN 60601-1:2006&A1:2013&AC:2014&A12:2014
60601-1 © IEC:2005 60601-1 © IEC:2005
- 337 - - 169 -
12.4.5.4 其他生产诊断或治疗辐射的医疗设备 如果适用,制造商应在风险管理过程中解决与产生诊断或治疗辐射的医疗设备(除了诊断X射线和放射治疗之外)相关的风险(请参见12.4.5.2和12.4.5.3)。
合规性通过检查风险管理文件来检查。
12.4.6 诊断或治疗声压 如果适用,制造商应在风险管理过程中解决与诊断或治疗声压相关的风险。
合规性通过检查风险管理文件来检查。
13 * 危险情况和故障条件
13.1 特定危险情况
- 概述
13.1.1 当应用4.7中描述并列在13.2中的单一故障条件时,任何一种危险情况(包括13.1.2至13.1.4)都不应发生在医疗设备中。
4.7描述了一次仅有一个元件故障可能导致危险情况的情况。
- 泄漏,外壳变形或超过最高温度
13.1.2 不得发生以下危险情况: - 恶劣数量下排放火焰、熔化金属、有毒或易燃物质; - ENCLOSURE变形以至于无法符合15.3.1要求;

当应用的部件温度超过表24中所指定的允许值时,应按照11.1.3描述的方式进行测量; 未被视为应用部件但可能被触摸的ME设备部件的温度超过表23中规定的允许值时,应按照11.1.3的方法进行测量和调整;

超过表22中“其他元件和材料”允许值的1.5倍减去12.5°C。绕组的限制在表26、表27和表31中找到。在所有其他情况下,适用表22的允许值。

应使用11.1.3中描述的方法进行温度测量。

对于发出火焰、熔融金属或易燃物质的单一故障条件,不得应用于以下部件和元件:

– 供应电路限制单一故障条件下功率耗散小于15W或能量耗散小于900J时,构造或供应电路部件。


4
你能否将"data/single.txt"的文本添加到问题中,而不是提供pdf的链接?你想要匹配什么内容?只有下面的一段话还是包括段落编号后面的文本也要匹配? - The fourth bird
1
当然可以!我现在刚刚添加了这段文本。 - wuddadid
1
如果你想匹配段落和下一个文本之间的文本,请尝试使用 ^\d+(?:\.\d+)* +.*(?:\r?\n(?!\d+(?:\.\d+)* ).*)*。https://regex101.com/r/eHXZ8x/1/ - The fourth bird
4个回答

1
你可以使用模式匹配空格,然后匹配其后的整行内容。接着重复匹配所有不以标题开头的后续行。
^\d+(?:\.\d+)* .*(?:\r?\n(?!\d+(?:\.\d+)* ).*)*
  • ^\d+(?:.\d+)* 匹配带有空格的标题的模式
  • .* 匹配除换行符外的任意字符0次或多次
  • (?: 非捕获组
    • \r?\n 匹配换行符
    • (?! 负向前瞻,断言右侧没有
      • \d+(?:.\d+)* 标题模式
    • ) 关闭前瞻
    • .* 匹配除换行符外的任意字符0次或多次
  • )* 关闭非捕获组并重复0次或多次以匹配所有行

正则表达式演示


那个正则表达式非常好用。它可以很好地找到标题!谢谢。 当你说“重复匹配所有不以标题开头的后续行”时,是指我要添加到你给出的正则表达式中还是创建一个带有不同正则表达式的if语句?如果这是一个愚蠢的问题,请原谅。 - wuddadid
1
这绝不是一个愚蠢的问题。模式应该首先匹配标题,然后是其余的行。然后当到达行尾时,您想要继续匹配换行符和整个下一行,只要它不以与标题匹配的模式开头即可。您不必添加任何内容到模式中,因为在匹配换行符 (?!\d+(?:\.\d+)* 后紧接着负向先行断言就会处理该部分。 - The fourth bird
好的,我的输出结果与正则表达式演示中的结果非常不同。我不知道我在这里做错了什么。这是输出链接:https://docdro.id/1hBvQXr 尽管我感觉答案很明显,但我仍在努力弄清楚这个问题。感谢您的耐心等待。 - wuddadid
1
不要逐行读取文件,可以尝试读取整个文件,然后使用findall。 - The fourth bird
1
@wuddadid 虽然另一个答案也可以,但你可以检查一下 regex101 演示链接的步骤数量,以比较两种模式的效率。 - The fourth bird
显示剩余2条评论

1
也许,
^(\d+(?:\.\d+)*)\s+([\s\S]*?)(?=^\d+(?:\.\d+)*)|^(\d+(?:\.\d+)*)\s+([\s\S]*)

可能会有些接近我猜测的所需文本。

在这里,我们只需要寻找以以下内容开头的行:

^(\d+(?:\.\d+)*)\s+

然后,我们只需要使用以下方法收集后续内容:

([\s\S]*?)

直到下一行以以下内容开头,

(?=^\d+(?:\.\d+)*)

然后,根据输入的情况,我们可能只剩下最后一个元素,我们可以使用 "last" 来收集它。
^(\d+(?:\.\d+)*)\s+([\s\S]*)

我们将使用|修改先前的表达式。

尽管这种方法编码简单,但在性能方面相当慢,因为我们使用了回顾,所以如果时间复杂度是一个问题,这里的其他答案会更好,这很可能会发生。

演示1

测试

import re

regex = r"^(\d+(?:\.\d+)*)\s+([\s\S]*?)(?=^\d+(?:\.\d+)*)|^(\d+(?:\.\d+)*)\s+([\s\S]*)"
string = """

I.S. EN 60601-1:2006&A1:2013&AC:2014&A12:2014

60601-1 © IEC:2005 
60601-1 © IEC:2005

– 337 – 
– 169 –

12.4.5.4  Other ME EQUIPMENT producing diagnostic or therapeutic radiation 
When  applicable,  the  MANUFACTURER  shall  address  in  the  RISK  MANAGEMENT PROCESS  the 
RISKS associated  with  ME EQUIPMENT  producing  diagnostic or therapeutic radiation  other  than 
for diagnostic X-rays and radiotherapy (see 12.4.5.2 and 12.4.5.3). 

Compliance is checked by inspection of the RISK MANAGEMENT FILE.

12.4.6  Diagnostic or therapeutic acoustic pressure 
When  applicable,  the  MANUFACTURER  shall  address  in  the  RISK  MANAGEMENT PROCESS  the 
RISKS associated with diagnostic or therapeutic acoustic pressure. 

Compliance is checked by inspection of the RISK MANAGEMENT FILE.

13  *  HAZARDOUS SITUATIONS and fault conditions

13.1  Specific HAZARDOUS SITUATIONS

*  General 

13.1.1 
When  applying  the  SINGLE  FAULT  CONDITIONS  as  described  in  4.7  and listed  in  13.2,  one  at  a 
time,  none  of  the  HAZARDOUS  SITUATIONS  in  13.1.2  to  13.1.4  (inclusive)  shall  occur  in  the 
ME EQUIPMENT.

The failure of any one component at a time, which could result in a  HAZARDOUS  SITUATION, is 
described in 4.7. 

*  Emissions, deformation of ENCLOSURE or exceeding maximum temperature 

13.1.2 
The following HAZARDOUS SITUATIONS shall not occur: 
–  emission  of  flames,  molten  metal,  poisonous  or  ignitable  substance  in  hazardous 

quantities; 

–  deformation of ENCLOSURES to such an extent that compliance with 15.3.1 is impaired; 
– 

temperatures  of  APPLIED  PARTS exceeding  the  allowed  values  identified  in  Table  24  when 
measured as described in 11.1.3; 
temperatures  of  ME EQUIPMENT  parts  that  are  not  APPLIED  PARTS but  are  likely  to  be 
touched,  exceeding  the  allowable  values  in  Table  23  when  measured  and  adjusted  as 
described in 11.1.3; 

– 

–  exceeding the allowable values for “other components and materials” identified in Table 22 
times 1,5 minus 12,5 °C. Limits for windings are found in Table 26, Table 27 and Table 31. 
In all other cases, the allowable values of Table 22 apply. 

Temperatures shall be measured using the method described in 11.1.3. 

The  SINGLE  FAULT  CONDITIONS  in  4.7,  8.1 b),  8.7.2  and  13.2.2,  with  regard  to  the  emission  of 
flames,  molten  metal  or  ignitable  substances,  shall  not  be  applied  to  parts  and  components 
where: 
–  The  construction  or  the  supply  circuit  limits  the  power  dissipation  in  SINGLE  FAULT 

CONDITION to less than 15 W or the energy dissipation to less than 900 J. 

"""

print(re.findall(regex, string, re.M))

输出

[('12.4.5.4', '对于除诊断X光和放射治疗之外的其他产生诊断或治疗辐射的医疗设备,制造商应在风险管理过程中解决与此相关的风险。\n合规性通过检查风险管理文件来验证。', '', ''), ('12.4.6', '对于诊断或治疗声压,制造商应在风险管理过程中解决与此相关的风险。\n合规性通过检查风险管理文件来验证。', '', ''), ('13', '* 危险情况和故障条件\n\n', '', ''), ('13.1', '特定的危险情况\n\n* 一般 \n\n', '', ''), ('13.1.1', '当应用4.7中描述并列在13.2中的单一故障条件时,不应出现13.1.2至13.1.4(含)中的任何危险情况。\n其中任何一个组件单独故障可能导致危险情况,在4.7中有所描述。\n* 排放、外壳变形或超过最高温度\n\n', '', ''), ('', '', '13.1.2', '不应发生以下危险情况:\n- 在危险数量中排放火焰、熔融金属、有毒或易燃物质;\n- 外壳变形,以至于无法符合15.3.1的要求;\n- 应用部件的温度超过表24中所示的允许值,在11.1.3中描述的测量时;\n- 可能被触摸的医疗设备部件的温度超过表23中允许的值,在11.1.3中描述的测量和调整时;\n- 其他组件和材料的允许值超过表22中的1.5倍减去12.5°C。绕组的极限值在表26、表27和表31中找到。在所有其他情况下,适用表22的允许值。\n温度应使用11.1.3中描述的方法进行测量。\n在构造或供应电路限制单一故障条件的功率耗散小于15 W或能量耗散小于900 J的部件和组件中,不应应用4.7、8.1 b)、8.7.2和13.2.2中描述的关于火焰、熔融金属或易燃物质的单一故障条件。


1
昨晚我最终成功地重现了你的输出结果。你能否简要解释一下你的正则表达式,因为我想采用你的答案...它似乎更符合我一直在寻找的东西。它需要一些调整,如果我能更好地理解它,我想我自己就能做到。谢谢! - wuddadid

0
import pdfplumber
import re
pdfToString = ""

with pdfplumber.open(r"sample.pdf") as pdf:
    for page in pdf.pages:
        print(page.extract_text())
        pdfToString += page.extract_text()

matches = re.findall(r'^\d+(?:\.\d+)* .*(?:\r?\n(?!\d+(?:\.\d+)* ).*)*',pdfToString, re.M)
for i in  matches:
    if "word_to_extract" in i[:50]:
        print(i)

这个解决方案是提取所有与问题中标题格式相同的标题,并提取所需的标题和其后面的段落。


0
由于他们详细的回答和有用的解释,我最终将@The-fourth-bird的代码部分和@Emma的代码部分结合起来,得到了这个正则表达式,它似乎很好地满足了我的需求。
(^\d+(?:\.\d+)*\s+)((?![a-z])[\s\S].*(?:\r?\n))([\s\S]*?)(?=^\d+(?:\.\d+)*\s+(?![a-z]))

这里是正则表达式演示

它可以做我想要的事情,即将(数字标题)、(文字标题)和(文本主体)分成由逗号分隔的组,从而使我能够使用自定义分隔符),(和一些其他后处理方法将它们分成Excel中的列。

这个新的正则表达式的好处在于它跳过了那些只是参考而不是实际标题的编号标题,就像这里看到的那样:

img


为什么不使用 https://regex101.com/r/034ARv/1 ^(\d+(?:\.\d+)*) (.*)((?:\r?\n(?!\d+(?:\.\d+)* ).*)*) 它需要更少的步骤。 - The fourth bird
针对我列出的特定用例,这提供了最佳结果。 - wuddadid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接