On dirait que la résolution de noms est finalement traitée par socket.create_connection
.
-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
Bien que, une fois le « Host: » En-tête a été défini, vous pouvez résoudre l'hôte et de transmettre l'adresse IP par le bas à l'ouvre.
Je vous suggère que vous sous-classe httplib.HTTPConnection
, et envelopper la méthode connect
de modifier self.host
avant de passer à socket.create_connection
.
sous-classe ensuite HTTPHandler
(et HTTPSHandler
) pour remplacer la méthode http_open
avec celui qui passe votre HTTPConnection
au lieu de son propre httplib à do_open
.
Comme ceci:
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']
Évidemment, il y a des problèmes de certificat si vous utilisez le protocole HTTPS, et vous devrez remplir MyResolver ...
Je ne pense pas que j'aurai besoin de HTTPS pour le moment, donc ça suffira parfaitement! Merci beaucoup! –
Il est également possible de surcharger 'HTTPConnection._create_connection', qui est disponible depuis Python 2.7.7 et 3.5 à cause de http://bugs.python.org/issue7776. –