Parece que la resolución del nombre se maneja finalmente por socket.create_connection
.
-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
Aunque una vez que el "Anfitrión:" encabezado se ha establecido, puede resolver el anfitrión y transmitir la dirección IP a través hasta el primer partido.
me gustaría sugerir que la subclase httplib.HTTPConnection
, y envolver el método connect
modificar self.host
antes de pasarla a socket.create_connection
.
Entonces subclase HTTPHandler
(y HTTPSHandler
) para reemplazar el método http_open
con uno que pasa a su HTTPConnection
en lugar de la propia httplib a do_open
.
De esta manera:
import urllib2
import httplib
import socket
def MyResolver(host):
if host == 'news.bbc.co.uk':
return '66.102.9.104' # Google IP
else:
return host
class MyHTTPConnection(httplib.HTTPConnection):
def connect(self):
self.sock = socket.create_connection((MyResolver(self.host),self.port),self.timeout)
class MyHTTPSConnection(httplib.HTTPSConnection):
def connect(self):
sock = socket.create_connection((MyResolver(self.host), self.port), self.timeout)
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
class MyHTTPHandler(urllib2.HTTPHandler):
def http_open(self,req):
return self.do_open(MyHTTPConnection,req)
class MyHTTPSHandler(urllib2.HTTPSHandler):
def https_open(self,req):
return self.do_open(MyHTTPSConnection,req)
opener = urllib2.build_opener(MyHTTPHandler,MyHTTPSHandler)
urllib2.install_opener(opener)
f = urllib2.urlopen('http://news.bbc.co.uk')
data = f.read()
from lxml import etree
doc = etree.HTML(data)
>>> print doc.xpath('//title/text()')
['Google']
Es obvio que hay problemas de certificado si se utiliza el HTTPS, y usted tiene que llenar MyResolver ...
No creo que necesite HTTPS por ahora, ¡así que esto será perfectamente suficiente! ¡Muchas gracias! –
También es posible anular 'HTTPConnection._create_connection', que está disponible desde Python 2.7.7 y 3.5 debido a http://bugs.python.org/issue7776. –