从字符串或 url 解析主机名和端口

Posted

技术标签:

【中文标题】从字符串或 url 解析主机名和端口【英文标题】:Parsing hostname and port from string or url 【发布时间】:2012-03-20 19:37:33 【问题描述】:

我可以得到以下任何格式的字符串:

网址:例如http://www.acme.com:456

字符串:例如 www.acme.com:456、www.acme.com 456 或 www.acme.com

我想提取主机,如果存在端口。如果端口值不存在,我希望它默认为 80。

我试过urlparse,它适用于url,但不适用于其他格式。例如,当我在 hostname:port 上使用 urlparse 时,它​​将主机名放在方案中而不是 netloc 中。

我会很高兴使用 urlparse 和正则表达式的解决方案,或者可以处理这两种格式的单个正则表达式。

【问题讨论】:

你试过什么正则表达式?如果不是正则表达式,你写的代码是什么? 【参考方案1】:

您可以使用 urlparse 从 URL 字符串中获取主机名:

from urlparse import urlparse
print urlparse("http://www.website.com/abc/xyz.html").hostname # prints www.website.com

【讨论】:

在 Python3 中使用:import urlliburllib.parse.urlparse('http://....')【参考方案2】:
>>> from urlparse import urlparse   
>>> aaa = urlparse('http://www.acme.com:456')

>>> aaa.hostname  
'www.acme.com'

>>> aaa.port   
456
>>> 

【讨论】:

我不知道为什么,但是当你以aaa = urlparse('www.acme.com:456') 运行它时,aaa.hostname 就是None,你知道为什么吗?顺便说一句,这正是问题所要问的 @RodrigoLaguna Real 迟到了,但这是一个悬而未决的问题。 urlparse('www.acme.com:456')urlparse('http://www.acme.com:456') 之间存在差异。从文档中,urlparse 假定一个符合 RFC1808 的 URL,并且除非使用 // - docs.python.org/2/library/urlparse.html#urlparse.urlparse 引入,否则不会正确识别网络位置。 Per @user1156544:在 Python3 中使用:导入 urllib 和 urllib.parse.urlparse('http://....')【参考方案3】:

我对 urlparse 不太熟悉,但是使用正则表达式你会做类似的事情:

p = '(?:http.*://)?(?P<host>[^:/ ]+).?(?P<port>[0-9]*).*'

m = re.search(p,'http://www.abc.com:123/test')
m.group('host') # 'www.abc.com'
m.group('port') # '123'

或者,没有端口:

m = re.search(p,'http://www.abc.com/test')
m.group('host') # 'www.abc.com'
m.group('port') # '' i.e. you'll have to treat this as '80'

编辑:固定正则表达式也匹配“www.abc.com 123”

【讨论】:

谢谢,这看起来真的很有用。 我假设否决票是因为这个解决方案过于复杂。我接受这一点,并同意 @ntziolis 的说法,即您应该尽可能尝试使用标准功能。 标准 urlparse 不适用于字符串(不是以 http(s) 或 // 开头),因此此解决方案似乎很有帮助。为什么不解释就投反对票。 这对于带有文字 IPv6 地址(如 http://[2001:db8:85a3::8a2e:370:7334]:80/test)的 URL 失败。【参考方案4】:

失败的原因:

www.acme.com 456

是因为它不是有效的 URI。你为什么不干脆:

    将空格替换为: 使用标准urlparse 方法解析生成的字符串

尽量使用默认功能,尤其是在解析 URI 等众所周知的格式时。

【讨论】:

当我在 host:port 上使用 urlparse 时,它​​会将主机名放入方案而不是 netloc。 来自手册:“遵循 RFC 1808 中的语法规范,urlparse 仅在由 '//' 正确引入时才识别 netloc。否则,输入被假定为相对 URL,因此从路径组件开始。” 我并不是说这是错误的,但它似乎不是处理主机名:端口格式的最佳方式。而且添加前缀看起来也不是很优雅。 基本上可以归结为:1. 在解析之前进行规范化(使用标准函数)还是 2. 在解析时尝试使用正则表达式或类似的东西来处理不同的格式。根据我的经验,最好进行标准化,因为正则表达式解决方案很容易出错 + 您正在复制现有功能。 目前,我想我将在 URL 上使用 urlparse,在主机名:端口格式上使用 @claesv 的正则表达式。【参考方案5】:

使用 urllib 的方法 -

    from urllib.parse import urlparse
    url = 'https://***.com/questions'
    print(urlparse(url))

输出 -

ParseResult(scheme='https', netloc='***.com', path='/questions', params='', query='', fragment='')

参考 - https://www.tutorialspoint.com/urllib-parse-parse-urls-into-components-in-python

【讨论】:

以上是关于从字符串或 url 解析主机名和端口的主要内容,如果未能解决你的问题,请参考以下文章

python 如何获取url信息

浅谈------location

如何用js获取浏览器URL中查询字符串的参数

如何从 Redshift 中的字符串中解析主机?

Outline解析SS URL

使用 spark.sql parse_url() 从包含大括号或管道的 URL 中提取主机