如何在文本文件中查找“复杂”的URL

时间:2018-04-06 19:29:20

标签: regex python-3.x

我正在使用以下正则表达式在文本文件中查找网址:

/http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+/

输出以下内容:

    http://rda.ucar.edu/datasets/ds117.0/.
    http://rda.ucar.edu/datasets/ds111.1/.
    http://www.discover-earth.org/index.html).
    http://community.eosdis.nasa.gov/measures/).

理想情况下,他们会打印出来:

    http://rda.ucar.edu/datasets/ds117.0/
    http://rda.ucar.edu/datasets/ds111.1/
    http://www.discover-earth.org/index.html
    http://community.eosdis.nasa.gov/measures/

关于如何调整我的正则表达式的任何想法?

提前谢谢!

更新 - 文本示例如下:

    this is a test http://rda.ucar.edu/datasets/ds117.0/. and I want this to                 be copied over http://rda.ucar.edu/datasets/ds111.1/. http://www.discover-earth.org/index.html). http://community.eosdis.nasa.gov/measures/). 

4 个答案:

答案 0 :(得分:1)

所以对于你在这里的网址: https://regex101.com/r/uSlkcQ/4

模式说明:

协议(例如https://

^[A-Za-z]{3,9}:(?://)

寻找经常性.[-;:&=+\$,\w]+ - 班级(www.sub.domain.com)

(?:[\-;:&=\+\$,\w]+\.?)+`

寻找定期/[\-;:&=\+\$,\w\.]+(/some.path/to/somewhere)

(?:\/[\-;:&=\+\$,\w\.]+)+

现在,针对您的特殊情况:使用负向前瞻确保最后一个字符不是圆点或括号

(?!\.|\)).

然后是完整的模式

^[A-Za-z]{3,9}:(?://)(?:[\-;:&=\+\$,\w]+\.?)+(?:\/[\-;:&=\+\$,\w\.]+)+(?!\.|\)).

答案 1 :(得分:1)

现有的正则表达式有一些改进或改变的方法可以让它起作用:

  • http[s]?可以更改为https?。他们是完全相同的。没有必要将s放在自己的角色类
  • [a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]您可以缩短整个内容并组合字符类,而不是在它们之间使用|。这不仅可以提高性能,还可以将某些范围组合到现有的字符类标记中。简化这一点,我们得到[a-zA-Z0-9$-_@.&+!*\(\),]
    • 我们可以更进一步:a-zA-Z0-9_\w相同。所以我们可以替换字符类中的那些来获取[\w$-@.&+!*\(\),]
    • 在原始正则表达式中,我们有$-_。这会创建一个范围,因此它实际上包含了ASCII表上$_之间的所有内容。这将导致不需要的字符匹配:$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_。有几个选项可以解决这个问题:
      • [-\w$@.&+!*\(\),]-放在角色类的开头
      • [\w$@.&+!*\(\),-]-放在角色类的末尾
      • [\w$\-@.&+!*\(\),]退出-,以便\-改为
    • 您不需要在角色类中转义()[\w$@.&+!*(),-]
  • [0-9a-fA-F][0-9a-fA-F]您不需要指定[0-9a-fA-F]两次。只需使用如下量词:[0-9a-fA-F]{2}
  • (?:%[0-9a-fA-F][0-9a-fA-F])这里实际上并不需要非捕获组,因此我们可以删除它(它增加了正则表达式引擎需要执行的另一个步骤,这是不必要的)

因此,简化现有正则表达式的结果如下:

https?://(?:[$\w@.&+!*(),-]|%[0-9a-fA-F]{2})+

现在您已经注意到它与/不匹配,因此我们需要将其添加到角色类中。您的正则表达式最初与此匹配,因为它具有不正确的范围$-_

https?://(?:[$\w@.&+!*(),/-]|%[0-9a-fA-F]{2})+

不幸的是,即使进行了此更改,它仍会在结尾处与).匹配。这是因为你的正则表达式在/之后没有被告知停止匹配。即使实现这一点,现在也会导致它与index.html之类的文件名不匹配。因此需要一个更好的解决方案。如果你给我几天时间,我正在开发一个与URL匹配的功能齐全的RFC兼容正则表达式。我想,在此期间,我至少会解释为什么你的正则表达式没有像你期望的那样工作。

答案 2 :(得分:1)

这将修剪包含跟踪字符) .

的输出
import re
regx= re.compile(r'(?m)[\.\)]+$')
print(regx.sub('', your_output))

这个正则表达式似乎可以从原始示例文本中提取URL

https?:[\S]*\/(?:\w+(?:\.\w+)?)?

Demo ,,,(从https?:[\S]*\/编辑)

Python脚本可能是这样的

ss=""" this is a test http://rda.ucar.edu/datasets/ds117.0/. and I want this to                 be copied over http://rda.ucar.edu/datasets/ds111.1/. http://www.discover-earth.org/index.html). http://community.eosdis.nasa.gov/measures/). """

regx= re.compile(r'https?:[\S]*\/(?:\w+(?:\.\w+)?)?')
for m in regx.findall(ss):
    print(m)

答案 3 :(得分:0)

感谢大家的回复。一位同事最终帮助我。这是解决方案:

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">