Sembra che la risoluzione dei nomi sia in definitiva gestita da socket.create_connection
.
-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
Anche se una volta il "Host:" intestazione è stato impostato, è possibile risolvere l'host e trasmettere l'indirizzo IP tramite verso il basso per la gara di apertura.
Io suggerirei che si sottoclasse httplib.HTTPConnection
, e avvolgere il metodo connect
per modificare self.host
prima di passarlo a socket.create_connection
.
Poi sottoclasse HTTPHandler
(e HTTPSHandler
) per sostituire il metodo http_open
con uno che passa la vostra HTTPConnection
invece di httplib proprio a do_open
.
Ti piace questa:
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']
Ovviamente ci sono problemi di certificati se si utilizza il protocollo HTTPS, e avrete bisogno di compilare MyResolver ...
Per ora non credo che avrò bisogno di HTTPS, quindi questo sarà perfettamente sufficiente! Grazie mille! –
È anche possibile eseguire l'override di 'HTTPConnection._create_connection', disponibile da Python 2.7.7 e 3.5 a causa di http://bugs.python.org/issue7776. –