2017-08-11 131 views
2

我想用urllib获取IPv6页面。 作品同方布拉克的IPv6格式,但我不知道如何(容易)说服蟒蛇做一个IPv6请求时,我给它的FQDN 像下面的IP为:https://www.dslreports.com/whatismyip在Python中使用urllib来获取带有FQDN的IPv6 URL

from sys import version_info 

PY3K = version_info >= (3, 0) 

if PY3K: 
    import urllib.request as urllib 
else: 
    import urllib2 as urllib 

url = None 
opener = urllib.build_opener() 
opener.addheaders = [('User-agent', 
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36")] 
url = opener.open("http://[2607:fad0:3706:1::1000]/whatismyip", timeout=3) 
content = url.read() 
+1

为了澄清,您希望在IPv4和IPv6地址都可用时始终使用IPv6地址? –

+0

是的,因为代码应该依次但不是按顺序检查IPv4然后检查IPv6。 –

回答

0

我终于解决了我的问题。不是最优雅的方式,但它适用于我。

阅读后:

Force requests to use IPv4/IPv6Python urllib2 force IPv4

,我决定做一个DNS查找,只需发送一个主机头使用FQDN抢内容。 (需要主机头的虚拟主机)

这是丑陋的代码片段:

# Ugly hack to get either IPv4 or IPv6 response from server 
parsed_uri = urlparse(server) 
fqdn = "{uri.netloc}".format(uri=parsed_uri) 
scheme = "{uri.scheme}".format(uri=parsed_uri) 
path = "{uri.path}".format(uri=parsed_uri) 

try: 
    ipVersion = ip_kind(fqdn[1:-1]) 
    ip = fqdn 
except ValueError: 
    addrs = socket.getaddrinfo(fqdn, 80) 
    if haveIPv6: 
     ipv6_addrs = [addr[4][0] for addr in addrs if addr[0] == socket.AF_INET6] 
     ip = "[" + ipv6_addrs[0] + "]" 
    else: 
     ipv4_addrs = [addr[4][0] for addr in addrs if addr[0] == socket.AF_INET] 
     ip = ipv4_addrs[0] 

server = "{}://{}{}".format(scheme, ip, path) 

url = urllib.Request(server, None, {'User-agent' : 'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5'}) 
# Next line adds the host header 
url.host = fqdn 
content = urllib.urlopen(url).read() 

这是很不理想,它可能是更清洁的,但它为我工作。

它在这里实现:https://github.com/SteveClement/ipgetter/tree/IPv6 这只是通过一个服务器列表,返回您的边界网关ip,现在也在IPv6中。

0

[更新:这条线关于Python 2/Python 3不再有效,因为问题已经更新]

首先,你似乎使用Python 2.这很重要,因为urllib模块已被拆分成若干部分并在Python 3中重命名。

其次,你的代码片段看起来不正确:build_opener不是一个函数离子可用urllib。它可用于urllib2。

所以,我认为你的代码实际上是在下列之一:

import urllib2 
opener = urllib2.build_opener() 
opener.addheaders = [('User-agent', 
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36")] 
url = opener.open("http://www.dslreports.com/whatismyip", timeout=3) 

如果你的DNS解析器正确处理IPv6资源记录,如果你的操作系统是建立与双堆栈IPv4/IPv6或单一IPv6仅堆栈,并且如果您有到dslreports.com的正确IPv6网络路径,则此Python程序将使用IPv6连接到www.dslreports.com。因此,没有必要说服python执行IPv6请求。

+0

嗯,我想我不是很清楚。正如你看到我的代码片段是python2和3的兼容代码。在python的精神层面上,显式更好地隐含。我不希望它依赖于用户正确配置IPv6的能力。您应该掌握是否使用v4或v6。 –