سؤال

أود أن أقول urllib2.urlopen (أو أ. فتاحة مخصصة) ليستخدم 127.0.0.1 (أو ::1) لحل العناوين. لن أغير بلدي /etc/resolv.conf, ، ومع ذلك.

حل واحد ممكن هو استخدام أداة مثل dnspython لاستعلام عناوين و httplib لبناء فتاحة URL مخصصة. كنت أفضل القول urlopen لاستخدام مخطط الأسماء العرف رغم ذلك. أي اقتراحات؟

هل كانت مفيدة؟

المحلول

يبدو أن حل الاسم يتم التعامل معه في نهاية المطاف بواسطة socket.create_connection.

-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection

على الرغم من أنه بمجرد تعيين رأس "المضيف:"، يمكنك حل المضيف وتمرير عنوان IP من خلال الفتح.

أود أن أقترح عليك فرعية httplib.HTTPConnection, ولف لف connect طريقة لتعديل self.host قبل اجتيازها socket.create_connection.

ثم الفئة الفرعية HTTPHandlerHTTPSHandler) ليحل محل 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 ...

نصائح أخرى

طريقة أخرى (قذرة) هي الترقيع القرد socket.getaddrinfo.

على سبيل المثال، يضيف هذا الرمز ذاكرة تخزين مؤقت (غير محدود) بحث DNS.

import socket
prv_getaddrinfo = socket.getaddrinfo
dns_cache = {}  # or a weakref.WeakValueDictionary()
def new_getaddrinfo(*args):
    try:
        return dns_cache[args]
    except KeyError:
        res = prv_getaddrinfo(*args)
        dns_cache[args] = res
        return res
socket.getaddrinfo = new_getaddrinfo

ستحتاج إلى تطبيق عميل بحث DNS الخاص بك (أو استخدام DNSPYTHON كما قلت). إن إجراء بحث الاسم في Glibc معقدة للغاية لضمان التوافق مع أنظمة أسماء DNS الأخرى. لا يوجد أي طريقة لتحديد خادم DNS معين في مكتبة Glibc على الإطلاق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top