Я хотел бы сказать urllib2.urlopen
(или пользовательский новичок) для использования 127.0.0.1
(или ::1
) разрешить адреса. Я не изменил бы мой /etc/resolv.conf
,как бы то ни было.
Одно возможное решение состоит в том, чтобы использовать инструмент как dnspython
запрашивать адреса и httplib
создавать пользовательского новичка URL. Я предпочел бы говорить urlopen
использовать пользовательский сервер имен все же. Какие-либо предложения?
Похоже, что разрешение имен в конечном итоге обрабатывается socket.create_connection
.
-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
Хотя после того, как заголовок «Host:» был установлен, вы можете разрешить хост и передать IP-адрес открывателю.
Я бы посоветовал вам создать подкласс httplib.HTTPConnection
и обернуть метод connect
для изменения self.host
перед его передачей в сокет . .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 ...
Вам нужно будет реализовать свой собственный клиент поиска dns (или использовать dnspython, как вы сказали). Процедура поиска имен в glibc довольно сложна для обеспечения совместимости с другими системами имен без dns. Например, в библиотеке glibc вообще нет возможности указать конкретный DNS-сервер.