我正在尝试找到一种简洁的方法来提取文本字符串中的所有网址。
经过广泛搜索后,我发现许多帖子建议使用正则表达式来完成任务,并且他们会给出正则表达式,这些表达式可以做到这一点。每个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并将参数带到:
我很高兴知道这件事。
答案 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)
答案 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'))]
根据我的口味有点过于密集,我不知道它的速度有多快,但它应该检测到最多的#34;理智的#34;字符串中的网址。