代码之家  ›  专栏  ›  技术社区  ›  Maddy

解析python中的IP地址和端口

  •  5
  • Maddy  · 技术社区  · 12 年前

    使用python,我想完成两件事:

    1. 需要将ipv6地址和端口组合以[fec2::10]:80的格式拆分为fec2::10和80。

    2. 给定IP地址和端口组合,我需要确定IP是v4还是v6地址。例如:1.2.3.4:80和[fec2::10]:80

    请建议一种方法。

    谢谢

    示例代码:

    #!/usr/bin/env python
    
    
    def main():
        server = "[fec1::1]:80"
        if server.find("[", 0, 2) == -1:
           print "IPv4"
           ip, port = server.split(':')
        else:
           print "IPv6"
           new_ip, port = server.rsplit(':', 1)
           print new_ip
           ip = new_ip.strip('[]')
    
        print ip
        print port
    
    if __name__ == '__main__':
        main()
    

    这适用于所有情况,除非指定输入时没有端口。例如:10.78.49.50和[fec2::10]

    对此有什么建议吗?

    3 回复  |  直到 4 年前
        1
  •  5
  •   jfs    12 年前

    假设 your_input 就像 "[fec2::10]:80" "1.2.3.4:80" ,很容易拆分端口并找到ip地址:

    #!/usr/bin/env python3
    from ipaddress import ip_address
    
    ip, separator, port = your_input.rpartition(':')
    assert separator # separator (`:`) must be present
    port = int(port) # convert to integer
    ip = ip_address(ip.strip("[]")) # convert to `IPv4Address` or `IPv6Address` 
    print(ip.version) # print ip version: `4` or `6`
    
        2
  •  3
  •   2rs2ts    12 年前

    您可以使用 urlparse (已调用 urllib.parse 在3.x中)将URL分离为其每个组件:

    >>> from urlparse import urlparse
    >>> ipv4address = urlparse("http://1.2.3.4:80")
    >>> ipv4address
    ParseResult(scheme='http', netloc='1.2.3.4:80', path='', params='', query='', fragment='')
    >>> ipv6address = urlparse("http://[fec2::10]:80")
    >>> ipv6address
    ParseResult(scheme='http', netloc='[fec2::10]:80', path='', params='', query='', fragment='')
    

    然后,您可以使用查找最后一个冒号的索引来分割端口 rfind :

    >>> ipv4address.netloc.rfind(':')
    7
    >>> ipv4address.netloc[:7], ipv4address.netloc[8:]
    ('1.2.3.4', '80')
    >>> ipv6address.netloc.rfind(':')
    10
    >>> ipv6address.netloc[:10], ipv6address.netloc[11:]
    ('[fec2::10]', '80')
    

    识别它是哪种类型应该很简单 if ':' in that_split_tuple[0] 正确的(不是100%确定,因为我已经有一段时间没有学会如何在URL中写入IPv6地址了。)

    最后,从IPv6地址中删除括号很简单,有很多方法可以做到:

    >>> ipv6address.netloc[:10].replace('[', '').replace(']', '')
    'fec2::10'
    >>> ipv6address.netloc[:10].strip('[]')
    'fec2::10'
    

    编辑 :由于您表示担心不总是有端口号,因此可以使用 regular expression :

    >>> import re
    >>> f = lambda(n): re.split(r"(?<=\]):" if n.startswith('[') else r"(?<=\d):", n)
    >>> f(ipv4address.netloc)
    ['1.2.3.4', '80']
    >>> f(ipv6address.netloc)
    ['[fec2::10]', '80']
    >>> f("1.2.3.4")
    ['1.2.3.4']
    >>> f("[fec2::10]")
    ['[fec2::10]']
    

    (我很难更巧妙地使用正则表达式,因此使用了内联三元。)

        3
  •  0
  •   Maddy    12 年前

    这是我想出的代码。它看起来冗长而费力,但它解决了所有可能的输入场景。任何关于精简/改进的建议都非常欢迎:)

    #!/usr/bin/env python
    
    import optparse
    
    def main():
        server = "[fec1::1]:80"
    
        if server.find("[", 0, 2) == -1:
           print "IPv4"
           if server.find(":", 0, len(server)) == -1:
              ip = server
              port = ""
           else:
              ip, port = server.split(':')
        else:
           print "IPv6"
           index = server.find("]", 0, len(server))
           if index == -1:
              print "Something wrong"
              new_ip = ""
              port = ""
           else:
              if server.find(":", index, len(server)) == -1:
                 new_ip = server
                 port = ""
              else:
                 new_ip, port = server.rsplit(':', 1)
           print new_ip
           ip = new_ip.strip('[]')
    
        print ip
        print port
    
    if __name__ == '__main__':
        main()