【问题标题】:Get protocol + host name from URL从 URL 获取协议 + 主机名
【发布时间】:2012-03-26 11:02:16
【问题描述】:

在我的 Django 应用程序中,我需要从 request.META.get('HTTP_REFERER') 中的引用者那里获取主机名及其协议,以便从以下 URL 获取:

我应该得到:

我查看了其他相关问题并找到了有关 urlparse 的信息,但此后并没有解决问题

>>> urlparse(request.META.get('HTTP_REFERER')).hostname
'docs.google.com'

【问题讨论】:

    标签: python django


    【解决方案1】:

    您应该可以使用urlparse(文档:python2python3):

    from urllib.parse import urlparse
    # from urlparse import urlparse  # Python 2
    parsed_uri = urlparse('http://stackoverflow.com/questions/1234567/blah-blah-blah-blah' )
    result = '{uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)
    print(result)
    
    # gives
    'http://stackoverflow.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://stackoverflow.com/questions/9626535/get-domain-name-from-url"
    base_url = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
    print(base_url)
    # http://stackoverflow.com/
    

    【讨论】:

      【解决方案4】:
      >>> import urlparse
      >>> url = 'http://stackoverflow.com/questions/1234567/blah-blah-blah-blah'
      >>> urlparse.urljoin(url, '/')
      'http://stackoverflow.com/'
      

      【讨论】:

      • 对于 Python 3,导入为 from urllib.parse import urlparse
      【解决方案5】:

      纯字符串操作:):

      >>> url = "http://stackoverflow.com/questions/9626535/get-domain-name-from-url"
      >>> url.split("//")[-1].split("/")[0].split('?')[0]
      'stackoverflow.com'
      >>> url = "stackoverflow.com/questions/9626535/get-domain-name-from-url"
      >>> url.split("//")[-1].split("/")[0].split('?')[0]
      'stackoverflow.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://stackoverflow.com:8080/some/folder?test=/questions/9626535/get-domain-name-from-url",
            "Stackoverflow.com:8080/some/folder?test=/questions/9626535/get-domain-name-from-url",
            "http://stackoverflow.com/some/folder?test=/questions/9626535/get-domain-name-from-url",
            "https://StackOverflow.com:8080?test=/questions/9626535/get-domain-name-from-url",
            "stackoverflow.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
        

        输出

        stackoverflow.com
        stackoverflow.com
        stackoverflow.com
        stackoverflow.com
        stackoverflow.com
        

        小提琴:https://pyfiddle.io/fiddle/23e4976e-88d2-4757-993e-532aa41b7bf0/?i=true

        【讨论】:

        • 恕我直言最好的解决方案,因为它很简单,而且它考虑了各种罕见的情况。谢谢!
        • 既不简单也不改进
        • 这不是问题的解决方案,因为您没有提供协议(https:// 或 http://)
        【解决方案9】:

        纯字符串操作有什么问题吗:

        url = 'http://stackoverflow.com/questions/9626535/get-domain-name-from-url'
        parts = url.split('//', 1)
        print parts[0]+'//'+parts[1].split('/', 1)[0]
        >>> http://stackoverflow.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://stackoverflow.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://stackoverflow.com/questions/9626535/get-protocol-host-name-from-url'
                hostname = url.split('/')[2] # stackoverflow.com
                origin = '/'.join(url.split('/')[:3]) # https://stackoverflow.com
                

                *Origin 用于XMLHttpRequest 标头

                【讨论】:

                  【解决方案15】:

                  这是获取任何域的根 URL 的简单方法。

                  from urllib.parse import urlparse
                  
                  url = urlparse('https://stackoverflow.com/questions/9626535/')
                  root_url = url.scheme + '://' + url.hostname
                  print(root_url) # https://stackoverflow.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
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2010-09-06
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-11-21
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-10-19
                      相关资源
                      最近更新 更多