从 URL 获取协议 + 主机名
Posted
技术标签:
【中文标题】从 URL 获取协议 + 主机名【英文标题】:Get protocol + host name from URL 【发布时间】:2012-03-26 11:02:16 【问题描述】:在我的 Django 应用程序中,我需要从 request.META.get('HTTP_REFERER')
中的引用者那里获取主机名及其协议,以便从以下 URL 获取:
我应该得到:
https://docs.google.com/ https://***.com/ http://www.example.com https://www.other-domain.com/我查看了其他相关问题并找到了有关 urlparse 的信息,但此后并没有解决问题
>>> urlparse(request.META.get('HTTP_REFERER')).hostname
'docs.google.com'
【问题讨论】:
【参考方案1】:您应该可以使用urlparse
(文档:python2、python3):
from urllib.parse import urlparse
# from urlparse import urlparse # Python 2
parsed_uri = urlparse('http://***.com/questions/1234567/blah-blah-blah-blah' )
result = 'uri.scheme://uri.netloc/'.format(uri=parsed_uri)
print(result)
# gives
'http://***.com/'
【讨论】:
这个答案添加一个/
到第三个例子http://www.domain.com
,但我认为这可能是问题的一个缺点,而不是答案。
@TokenMacGuy:是的,我的错...没有注意到丢失的 /
我认为这不是一个好的解决方案,因为netloc
不是域:尝试urlparse.urlparse('http://user:pass@example.com:8080')
并发现它提供了'user:pass@'
和':8080'
之类的部分
urlparse 模块在 Python 3 中被重命名为 urllib.parse。所以,from urllib.parse import urlparse
这回答了作者的意思,而不是实际陈述的内容。对于那些寻找域名而不是主机名的人(如本解决方案提供的那样),我建议查看 dm03514 目前在下面的答案。 Python 的 urlparse 不能给你域名。这似乎是一个疏忽。【参考方案2】:
https://github.com/john-kurkowski/tldextract
这是一个更详细的 urlparse 版本。它会为您检测域和子域。
来自他们的文档:
>>> import tldextract
>>> tldextract.extract('http://forums.news.cnn.com/')
ExtractResult(subdomain='forums.news', domain='cnn', suffix='com')
>>> tldextract.extract('http://forums.bbc.co.uk/') # United Kingdom
ExtractResult(subdomain='forums', domain='bbc', suffix='co.uk')
>>> tldextract.extract('http://www.worldbank.org.kg/') # Kyrgyzstan
ExtractResult(subdomain='www', domain='worldbank', suffix='org.kg')
ExtractResult
是一个命名元组,所以很容易访问你想要的部分。
>>> ext = tldextract.extract('http://forums.bbc.co.uk')
>>> ext.domain
'bbc'
>>> '.'.join(ext[:2]) # rejoin subdomain and domain
'forums.bbc'
【讨论】:
这是所写问题的正确答案,如何获取域名。选择的解决方案提供了 HOSTNAME,我相信这是作者首先想要的。【参考方案3】:Python3 使用urlsplit:
from urllib.parse import urlsplit
url = "http://***.com/questions/9626535/get-domain-name-from-url"
base_url = "0.scheme://0.netloc/".format(urlsplit(url))
print(base_url)
# http://***.com/
【讨论】:
【参考方案4】:>>> import urlparse
>>> url = 'http://***.com/questions/1234567/blah-blah-blah-blah'
>>> urlparse.urljoin(url, '/')
'http://***.com/'
【讨论】:
对于 Python 3,导入为from urllib.parse import urlparse
。【参考方案5】:
纯字符串操作:):
>>> url = "http://***.com/questions/9626535/get-domain-name-from-url"
>>> url.split("//")[-1].split("/")[0].split('?')[0]
'***.com'
>>> url = "***.com/questions/9626535/get-domain-name-from-url"
>>> url.split("//")[-1].split("/")[0].split('?')[0]
'***.com'
>>> url = "http://foo.bar?haha/whatever"
>>> url.split("//")[-1].split("/")[0].split('?')[0]
'foo.bar'
就是这样,伙计们。
【讨论】:
不错且简单的选项,但在某些情况下会失败,例如foo.bar?haha @SimonSteinberger :-) 这个怎么样:url.split("//")[-1].split("/")[0].split('?')[0]
:-))【参考方案6】:
标准库函数urllib.parse.urlsplit() 就是您所需要的。以下是 Python3 的示例:
>>> import urllib.parse
>>> o = urllib.parse.urlsplit('https://user:pass@www.example.com:8080/dir/page.html?q1=test&q2=a2#anchor1')
>>> o.scheme
'https'
>>> o.netloc
'user:pass@www.example.com:8080'
>>> o.hostname
'www.example.com'
>>> o.port
8080
>>> o.path
'/dir/page.html'
>>> o.query
'q1=test&q2=a2'
>>> o.fragment
'anchor1'
>>> o.username
'user'
>>> o.password
'pass'
【讨论】:
【参考方案7】:如果您认为您的网址有效,那么这将一直有效
domain = "http://google.com".split("://")[1].split("/")[0]
【讨论】:
最后一个split
是错误的,没有更多的正斜杠可以分割。
不会有问题,如果没有更多的斜线,列表将返回一个元素。所以无论有没有斜线它都会起作用
我编辑了您的答案,以便能够删除反对票。很好的解释。谢了。【参考方案8】:
这是一个稍微改进的版本:
urls = [
"http://***.com:8080/some/folder?test=/questions/9626535/get-domain-name-from-url",
"***.com:8080/some/folder?test=/questions/9626535/get-domain-name-from-url",
"http://***.com/some/folder?test=/questions/9626535/get-domain-name-from-url",
"https://***.com:8080?test=/questions/9626535/get-domain-name-from-url",
"***.com?test=questions&v=get-domain-name-from-url"]
for url in urls:
spltAr = url.split("://");
i = (0,1)[len(spltAr)>1];
dm = spltAr[i].split("?")[0].split('/')[0].split(':')[0].lower();
print dm
输出
***.com
***.com
***.com
***.com
***.com
小提琴:https://pyfiddle.io/fiddle/23e4976e-88d2-4757-993e-532aa41b7bf0/?i=true
【讨论】:
恕我直言最好的解决方案,因为它很简单,而且它考虑了各种罕见的情况。谢谢! 既不简单也不改进 这不是问题的解决方案,因为您没有提供协议(https:// 或 http://)【参考方案9】:纯字符串操作有什么问题吗:
url = 'http://***.com/questions/9626535/get-domain-name-from-url'
parts = url.split('//', 1)
print parts[0]+'//'+parts[1].split('/', 1)[0]
>>> http://***.com
如果您更喜欢附加斜杠,请扩展此脚本,如下所示:
parts = url.split('//', 1)
base = parts[0]+'//'+parts[1].split('/', 1)[0]
print base + (len(url) > len(base) and url[len(base)]=='/'and'/' or '')
这大概可以优化一下...
【讨论】:
没有错,但我们有一个已经完成工作的工具,我们不要重新发明***;)【参考方案10】:这有点迟钝,但在两个方向上都使用urlparse
:
import urlparse
def uri2schemehostname(uri):
urlparse.urlunparse(urlparse.urlparse(uri)[:2] + ("",) * 4)
那个奇怪的 ("",) * 4
位是因为 urlparse 需要 完全 len(urlparse.ParseResult._fields)
= 6
【讨论】:
【参考方案11】:我知道这是一个老问题,但我今天也遇到了。 用单线解决了这个问题:
import re
result = re.sub(r'(.*://)?([^/?]+).*', '\g<1>\g<2>', url)
【讨论】:
【参考方案12】:您可以简单地使用带有相对根“/”作为第二个参数的 urljoin:
import urllib.parse
url = 'https://***.com/questions/9626535/get-protocol-host-name-from-url'
root_url = urllib.parse.urljoin(url, '/')
print(root_url)
【讨论】:
【参考方案13】:可以通过re.search()解决
import re
url = 'https://docs.google.com/spreadsheet/ccc?key=blah-blah-blah-blah#gid=1'
result = re.search(r'^http[s]*:\/\/[\w\.]*', url).group()
print(result)
#result
'https://docs.google.com'
【讨论】:
【参考方案14】:获取域/主机名和来源*
url = 'https://***.com/questions/9626535/get-protocol-host-name-from-url'
hostname = url.split('/')[2] # ***.com
origin = '/'.join(url.split('/')[:3]) # https://***.com
*Origin
用于XMLHttpRequest
标头
【讨论】:
【参考方案15】:这是获取任何域的根 URL 的简单方法。
from urllib.parse import urlparse
url = urlparse('https://***.com/questions/9626535/')
root_url = url.scheme + '://' + url.hostname
print(root_url) # https://***.com
【讨论】:
【参考方案16】:如果它包含少于 3 个斜线,那么你就有了,如果没有,那么我们可以找到它之间的出现:
import re
link = http://forum.unisoftdev.com/something
slash_count = len(re.findall("/", link))
print slash_count # output: 3
if slash_count > 2:
regex = r'\:\/\/(.*?)\/'
pattern = re.compile(regex)
path = re.findall(pattern, url)
print path
【讨论】:
以上是关于从 URL 获取协议 + 主机名的主要内容,如果未能解决你的问题,请参考以下文章