使用正则表达式从Python字符串中提取超链接文本

使用正则表达式从Python字符串中提取超链接文本,python,regex,Python,Regex,我试图提取一个巨大字符串中每个超链接的显示文本。(字符串是通过打开和读取.rtf文件获得的,该文件有许多超链接。)超链接的格式通常为{\field{\*\fldinst HYPERLINK”http://www.mywebsite.com/“}{\fldrslt Click Here}(我想单击此处),但通常包含许多带换行符的嵌套格式: 示例1(我想提取Leonard T.Strand):文本我不想要{\\field{\\*\\fldinst超链接”http://www.westlaw.com/

我试图提取一个巨大字符串中每个超链接的显示文本。(字符串是通过打开和读取.rtf文件获得的,该文件有许多超链接。)超链接的格式通常为
{\field{\*\fldinst HYPERLINK”http://www.mywebsite.com/“}{\fldrslt Click Here}
(我想单击此处),但通常包含许多带换行符的嵌套格式:

示例1(我想提取Leonard T.Strand):
文本我不想要{\\field{\\*\\fldinst超链接”http://www.westlaw.com/Link/Document/FullText?findType=h&pubNum=176284&cite=0226771601&originatingDoc=I2e197170e0a011eaa13ca2bed92d37fc&refType=RQ&originationContext=document&vr=3.0&rs=cblt1.0&transitionType=DocumentItem&contextData=(sc.Search)“}{\\fldrslt\n{\\b0\\cf5\\f2\\ul0\\strike0\\i0\\fs20\\sa0\\sb0\nloard T.Strand\n}}}我不想要的文本

示例2(我想摘录Morgan v.Robinson和920 F.3d 521523(第八巡回法庭,2019年):
文本我不想要{\\field{\\*\\fldinst超链接"http://www.westlaw.com/Link/Document/FullText?findType=Y&serNum=2047938005&pubNum=0000506&originatingDoc=I2e197170e0a011eaa13ca2bed92d37fc&refType=RP&fi=co_pp_sp_506_523&originationContext=document&vr=3.0&rs=cblt1.0&transitionType=DocumentItem&contextData=(sc.Search)#co#pp_sp_506_523“}{\\fldrslt\n{\\b0\\cf5\\f2\\i1\\fs20\n{\\b0\\cf5\\f2\\ul0\\strike0\\i1\\fs20\\sa0\\sb0\n摩根诉罗宾逊案\n}\n}\n{\\b0\\cf5\\f2\\ul0\\strike0\\i0\\fs20\\sa0\\sb0\n,920 F.3d 521523(2019年第八巡回法庭)\n}我不想要的文本


这适用于第一种类型,但不适用于第二种:
regex=re.compile('\n?\}?\n\{\\\\field.\\\\fldrslt\n.*\n(.*)\n')
理想情况下,我想要一种更具通用性的东西,以适应超链接的广泛结构,但示例2中的多个文本位置给我带来了问题。

查看示例数据,您可能会对
字段和
fldinst
部分使用特定的匹配。然后在
fldinst
部分之后,匹配其余部分e行,然后是以
{

然后捕获组1中的以下所有行,直到遇到
}

然后从捕获组1中,删除以
{
}
或逗号开头的所有行

注意这是基于示例数据,不考虑平衡的花括号

获取组1的模式

{\\\\field\s*{\\\\\*\\\\fldinst HYPERLINK\s+"https?://[^"]+"\s+}{\\\\fldrslt.*\r?\n((?:(?!}}}).*\r?\n)*)}}}
关于图案

  • {\\\\field\s*{\\\\\\\fldinst HYPERLINK\s+“https?”://[^”]+“\s+}
    匹配字段和超链接部分
  • {\\\\fldrslt.*\r?\n
    匹配fldrslt部分
  • Capturegroup 1
    • (?:(?!}}})。*\r?\n)*
      重复匹配所有不以
      }}开头的行
  • 关闭第1组
  • }}
    匹配结尾
    }}

从组1中删除所有不需要的线的模式

^(?:[{}].*[\r\n]*|,[^\S\r\n]*)
  • ^
    字符串的开头
  • (?:
    非捕获组
    • [{}].[\r\n]*
      匹配以
      {
      }
    • |
    • ,[^\S\r\n]*
      匹配一个
      后跟不带换行符的可选空格字符
  • 关闭组

示例代码

import re
 
regex = r"{\\\\field\s*{\\\\\*\\\\fldinst HYPERLINK\s+\"https?://[^\"]+\"\s+}{\\\\fldrslt.*\r?\n((?:(?!}}}).*\r?\n)*)}}}"
 
test_str = ("text I don't want {\\\\field {\\\\*\\\\fldinst HYPERLINK \"http://w...content-available-to-author-only...w.com/Link/Document/FullText?findType=Y&serNum=2047938005&pubNum=0000506&originatingDoc=I2e197170e0a011eaa13ca2bed92d37fc&refType=RP&fi=co_pp_sp_506_523&originationContext=document&vr=3.0&rs=cblt1.0&transitionType=DocumentItem&contextData=(sc.Search)#co_pp_sp_506_523\" }{\\\\fldrslt \n"
            "{\\\\b0 \\\\cf5 \\\\f2 \\\\i1 \\\\fs20 \n"
            "{\\\\b0 \\\\cf5 \\\\f2 \\\\ul0 \\\\strike0 \\\\i1 \\\\fs20 \\\\sa0 \\\\sb0 \n"
            "Morgan v. Robinson\n"
            "}\n"
            "}\n"
            "{\\\\b0 \\\\cf5 \\\\f2 \\\\ul0 \\\\strike0 \\\\i0 \\\\fs20 \\\\sa0 \\\\sb0 \n"
            ", 920 F.3d 521, 523 (8th Cir. 2019)\n"
            "}}} text I don't want\n\n"
            "text I don't want {\\\\field {\\\\*\\\\fldinst HYPERLINK \"http://w...content-available-to-author-only...w.com/Link/Document/FullText?findType=h&pubNum=176284&cite=0226771601&originatingDoc=I2e197170e0a011eaa13ca2bed92d37fc&refType=RQ&originationContext=document&vr=3.0&rs=cblt1.0&transitionType=DocumentItem&contextData=(sc.Search)\" }{\\\\fldrslt \n"
            "{\\\\b0 \\\\cf5 \\\\f2 \\\\ul0 \\\\strike0 \\\\i0 \\\\fs20 \\\\sa0 \\\\sb0 \n"
            "Leonard T. Strand\n"
            "}}} text I don't want")
 
for g in re.findall(regex, test_str):
    print(re.sub(r"^(?:[{}].*[\r\n]*|,[^\S\r\n]*)", "", g, 0, re.MULTILINE))
输出

Morgan v. Robinson
920 F.3d 521, 523 (8th Cir. 2019)

Leonard T. Strand

为什么不匹配“HYPERLINK\s+”(http.*?)然后使用组1?