Похоже, что разрешение имени в конечном итоге обрабатывается socket.create_connection
.
-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
Хотя когда-то «Host:» заголовок был установлен, вы можете разрешить хост и передать IP-адрес через вниз нож.
Я предлагаю вам подкласс httplib.HTTPConnection
и перенесите метод connect
изменить self.host
перед передачей его в socket.create_connection
.
Тогда подкласс HTTPHandler
(и HTTPSHandler
), чтобы заменить метод http_open
с одним, который проходит ваш HTTPConnection
вместо HTTPLIB собственного к do_open
.
Как это:
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']
Очевидно, есть вопросы сертификата, если вы используете HTTPS, и вам необходимо заполнить MyResolver ...
Я не думаю, что мне понадобится HTTPS, так что этого вполне хватит! Большое спасибо! –
Также возможно переопределить 'HTTPConnection._create_connection', который доступен с Python 2.7.7 и 3.5 из-за http://bugs.python.org/issue7776. –