从字符串或 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 urllib
和 urllib.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 解析主机名和端口的主要内容,如果未能解决你的问题,请参考以下文章