Dường như độ phân giải tên cuối cùng được xử lý bởi socket.create_connection
.
-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
Mặc dù một khi tiêu đề "Máy chủ lưu trữ:" đã được đặt, bạn có thể giải quyết máy chủ và chuyển địa chỉ IP qua trình mở.
Tôi khuyên bạn nên phân loại httplib.HTTPConnection
và quấn phương thức connect
để sửa đổi self.host
trước khi chuyển đến socket.create_connection
.
Sau đó phân lớp HTTPHandler
(và HTTPSHandler
) để thay thế cho phương pháp http_open
với một mà đi của bạn HTTPConnection
thay vì httplib của riêng để do_open
.
Như thế này:
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']
Rõ ràng có những vấn đề chứng chỉ nếu bạn sử dụng HTTPS, và bạn sẽ cần phải điền MyResolver ...
Tôi không nghĩ mình sẽ cần HTTPS ngay bây giờ, vì vậy điều này sẽ hoàn toàn đủ! Cảm ơn nhiều! –
Cũng có thể ghi đè lên 'HTTPConnection._create_connection', có sẵn từ Python 2.7.7 và 3.5 do http://bugs.python.org/issue7776. –