如何在使用urllib2连接后确定服务器的IP地址?

4 投票
4 回答
7781 浏览
提问于 2025-04-17 10:34

我正在使用urllib2从服务器下载数据。但是我需要知道我连接的服务器的IP地址。

import urllib2
STD_HEADERS = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,
                    */*;q=0.8',
                'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
                'Accept-Language': 'en-us,en;q=0.5',
                'User-Agent': 'Mozilla/5.0 (X11; U; Linux x86_64;en-US;rv:1.9.2.12)     
                           Gecko/20101028 Firefox/3.6.12'}
request = urllib2.Request(url, None, STD_HEADERS)
data =  urllib2.urlopen(request)

请不要让我通过网址来查找IP地址,因为在出现“HTTP重定向”或者负载均衡服务器的情况下,这样做不能保证下载数据的服务器和查询到的IP地址是同一个。

4 个回答

3

我知道这个问题已经很久了,但我发现通过urllib2返回的响应对象里面包含了IP地址。这看起来有点像是个小技巧,但确实有效。

import urllib2
STD_HEADERS = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,
                    */*;q=0.8',
                'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
                'Accept-Language': 'en-us,en;q=0.5',
                'User-Agent': 'Mozilla/5.0 (X11; U; Linux x86_64;en-US;rv:1.9.2.12)     
                           Gecko/20101028 Firefox/3.6.12'}
request = urllib2.Request(url, None, STD_HEADERS)
data =  urllib2.urlopen(request)

data.fp._sock.fp._sock.getpeername()
7

这是我在Python 2.7上用得不错的方法:

>>> from urllib2 import urlopen
>>> from socket import fromfd
>>> from socket import AF_INET
>>> from socket import SOCK_STREAM
>>> r = urlopen('http://stackoverflow.com/')
>>> mysockno = r.fileno()
>>> mysock = fromfd( mysockno, AF_INET, SOCK_STREAM)
>>> (ip, port) = mysock.getpeername()
>>> print "got IP %s port %d" % (ip, port)
got IP 198.252.206.140 port 80
3
import urllib2, socket, urlparse

# set up your request as before, then:
data = urllib2.urlopen(request)
addr = socket.gethostbyname(urlparse.urlparse(data.geturl()).hostname)

data.geturl() 会返回实际用来获取资源的 URL,这个 URL 是在经历了任何重定向之后的结果。接着,我们用 urlparse 从中提取出主机名,然后把这个主机名交给 socket.gethostbyname 来获取对应的 IP 地址。

有些主机可能会为同一个主机名提供多个 IP 地址,所以请求可能是由不同的服务器处理的,但这已经是你能得到的最接近的结果了。在 URL 请求之后立刻调用 gethostbyname,它会使用你的 DNS 缓存,除非你处理的时间很短,比如 1 秒,否则你得到的还是刚才用过的同一服务器。

如果这样还不够,你可以尝试开一个线程,在仍然连接到远程服务器的情况下执行 lsof。我相信你可以让 urllib2 保持连接一段时间,这样就能成功。不过,这样做似乎比实际需要的要复杂得多。

撰写回答