使用python3提取字符串中的所有URL

时间:2017-06-20 05:28:00

标签: python regex python-3.x url

我正在尝试找到一种简洁的方法来提取文本字符串中的所有网址。

经过广泛搜索后,我发现许多帖子建议使用正则表达式来完成任务,并且他们会给出正则表达式,这些表达式可以做到这一点。每个RegEx都有一些优势和一些缺点。另外,编辑它们以改变它们的行为并不是直截了当的。无论如何,在这一点上,我对能够正确检测本文中网址的任何RegEx感到满意:

输入:

  

Lorem ipsum dolor sit amet https://www.lorem.com/ipsum.php?q=suas,nusquam tincidunt ex per,ius modus integre no,quando utroque placerat qui no。 Mea endingemque vituperatoribus et,omnes malorum est id,pri omnes atomorum expetenda ex。 Elit pertinacia没有eos,nonumy comprehensam id mei。 Ei eum maiestatis quaerendum https://www.lorem.org。 Pri posse constituam in,http://news.bbc.co.uk omnium assentior definitionem ei。 Cu duo equidem meliore qualisque。

输出:

  

[' https://www.lorem.com/ipsum.php?q=suas',' https://www.lorem.org',' http://news.bbc.co.uk']

但是如果有一个python3类/函数/库,它会找到给定文本中的所有url并将参数带到:

  1. 选择要检测的协议
  2. 选择允许的TLD
  3. 选择允许的域名
  4. 我很高兴知道这件事。

5 个答案:

答案 0 :(得分:3)

除了其他人提到的内容之外,由于您已经要求提供已存在的内容,因此您可能需要尝试URLExtract

显然它试图在给定的文本中找到 TLD 的任何出现。如果找到TLD,则从该位置开始向两侧扩展边界以搜索"停止字符" (通常是空格,逗号,单引号或双引号)。

您有几个例子here

from urlextract import URLExtract

extractor = URLExtract()
urls = extractor.find_urls("Let's have URL youfellasleepwhilewritingyourtitle.com as an example.")
print(urls) # prints: ['youfellasleepwhilewritingyourtitle.cz']

该模块似乎还有update()方法,可让您更新 TLD 列表缓存文件

但是,如果这不符合您的特定要求,您可以在使用上述模块(或任何其他解析URL的方式)处理网址后手动执行一些检查。例如,假设您获得了一个URL列表:

result = ['https://www.lorem.com/ipsum.php?q=suas', 'https://www.lorem.org', 'http://news.bbc.co.uk'] 

然后,您可以构建另一个包含排除域/ TLD /等的列表:

allowed_protocols = ['protocol_1', 'protocol_2']
allowed_tlds = ['tld_1', 'tld_2', 'tld_3']
allowed_domains = ['domain_1']

for each_url in results:
    # here, check each url against your rules

答案 1 :(得分:2)

如果你想要一个正则表达式,你可以使用它:

import re


string = "Lorem ipsum dolor sit amet https://www.lorem.com/ipsum.php?q=suas, nusquam tincidunt ex per, ius modus integre no, quando utroque placerat qui no. Mea conclusionemque vituperatoribus et, omnes malorum est id, pri omnes atomorum expetenda ex. Elit pertinacia no eos, nonumy comprehensam id mei. Ei eum maiestatis quaerendum https://www.lorem.org. Pri posse constituam in, sit http://news.bbc.co.uk omnium assentior definitionem ei. Cu duo equidem meliore qualisque."

result = re.findall(r"\w+://\w+\.\w+\.\w+/?[\w\.\?=#]*", string)
print(result)

输出:

['https://www.lorem.com/ipsum.php?q=suas', 
 'https://www.lorem.org', 
 'http://news.bbc.co.uk']

答案 2 :(得分:1)

import re
import string
text = """
Lorem ipsum dolor sit amet https://www.lore-m.com/ipsum.php?q=suas, 
nusquam tincidunt ex per, ftp://link.com ius modus integre no, quando utroque placerat qui no. 
Mea conclusionemque vituperatoribus et, omnes malorum est id, pri omnes atomorum expetenda ex. 
Elit ftp://link.work.in pertinacia no eos, nonumy comprehensam id mei. Ei eum maiestatis quaerendum https://www.lorem.org. 
Pri posse constituam in, sit http://news.bbc.co.uk omnium assentior definitionem ei. Cu duo equidem meliore 
qualisque.
"""

URL_REGEX = r"""((?:(?:https|ftp|http)?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|org|uk)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|uk|ac)\b/?(?!@)))"""

urls = re.findall(URL_REGEX, text)
print([''.join(x for x in url if x in string.printable) for url in urls])

现在,如果您只想保留包含有效域名的网址,可以按以下方式编写:

VALID_DOMAINS = ['lorem.org', 'bbc.co.uk', 'sample.com', 'link.net']
valid_urls = []
for url in result_url:
    for val_domain in VALID_DOMAINS:
        if val_domain in url:
            valid_urls.append(url)
print(valid_urls)

答案 3 :(得分:0)

output = [x for x in input().split() if x.startswith('http://') or x.startswith('https://') or x.startswith('ftp://')]
print(output)

你的例子: http://ideone.com/wys57x

毕竟,如果它不是一个字母,你也可以删除列表元素中的最后一个字符。

修改

output = [x for x in input().split() if x.startswith('http://') or x.startswith('https://') or x.startswith('ftp://')]
newOutput = []
for link in output:
    copy = link
    while not copy[-1].isalpha():
        copy = copy[:-1]
    newOutput.append(copy)
print(newOutput)

您的示例:http://ideone.com/gHRQ8w

答案 4 :(得分:0)

使用现有的库可能是最好的解决方案。

但这对我的小剧本来说太过分了,而且 - 受到@ piotr-wasilewiczs回答的启发 - 我想出了:

from string import ascii_letters
links = [x for x in line.split() if x.strip(str(set(x) - set(ascii_letters))).startswith(('http', 'https', 'www'))]
  • 对于该行中的每个单词
  • strip(从开头到结尾)在单词本身中找到的非ASCII字母)
  • 并按以https,http,www。
  • 之一开头的字词进行过滤

根据我的口味有点过于密集,我不知道它的速度有多快,但它应该检测到最多的#34;理智的#34;字符串中的网址。