【问题标题】:Using regex to extract hyperlink text from Python string使用正则表达式从 Python 字符串中提取超链接文本
【发布时间】:2020-11-21 07:33:33
【问题描述】:

我正在尝试提取巨大字符串中每个超链接的显示文本。 (字符串是通过打开和读取一个.rtf文件得到的,该文件有很多超链接。)超链接的格式一般是{\field{\*\fldinst HYPERLINK "http://www.mywebsite.com/"}{\fldrslt Click Here}}(我要点击这里),但往往包含很多带有换行符的嵌套格式:

示例 1(我要提取 Leonard T. Strand):text I don't want {\\field {\\*\\fldinst HYPERLINK "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 \nLeonard T. Strand\n}}} text I don't want

示例 2(我想提取 Morgan v. Robinson 和 920 F.3d 521、523(8th Cir. 2019):text I don't want {\\field {\\*\\fldinst HYPERLINK "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 \nMorgan 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

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

【问题讨论】:

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

标签: python regex


【解决方案1】:

查看示例数据,您可能会对fieldfldinst 部分使用特定匹配。然后在fldinst 之后匹配该行的其余部分,然后是所有以{ 开头的行

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

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

注意这是基于示例数据,并未考虑平衡大括号。

获取组 1 的模式

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

关于模式

  • {\\\\field\s*{\\\\\*\\\\fldinst HYPERLINK\s+"https?://[^"]+"\s+} 匹配 字段 和 HYPERLINK 部分
  • {\\\\fldrslt.*\r?\n 匹配 fldrslt 部分
  • ( 捕获第 1 组
    • (?:(?!}}}).*\r?\n)* 重复匹配所有不以}}} 开头的行
  • )关闭第一组
  • }}}比赛结束}}}

Regex demo

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

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

Regex demo

示例代码

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

Python demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    相关资源
    最近更新 更多