Fortæl urllib2 til at bruge brugerdefinerede DNS –

Jeg vil gerne fortælle urllib2.urlopen (eller en brugerdefinerede oplukker) til at bruge 127.0.0.1 (eller ::1) til at løse adresser. Jeg ville ikke ændre min /etc/resolv.conf, dog.

En mulig løsning er at bruge et værktøj som dnspython til at søge adresser og httplib til at bygge en brugerdefineret url-opener. Jeg foretrækker at fortælle urlopen til at bruge en brugerdefineret nameserver selv. Nogen forslag?

OriginalForfatteren Attila O. | 2010-02-10

3 svar

  1. 21

    Ligner navn beslutningen er i sidste ende håndteres af socket.create_connection.

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

    Selv når “Host:” header er blevet indstillet, kan du løse vært og videregive IP-adresse via ned til åbneren.

    Jeg vil foreslå, at du underklasse httplib.HTTPConnection, og pak connect metode til at ændre self.host, før den ledes til socket.create_connection.

    Så underklasse HTTPHandler (og HTTPSHandler) til at erstatte de http_open metode med en, der passerer din HTTPConnection i stedet for httplib ‘ s egne til at do_open.

    Som denne:

    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']

    Der er naturligvis certifikat problemer, hvis du bruger HTTPS, og du bliver nødt til at udfylde MyResolver…

    Jeg tror ikke, jeg får brug for HTTPS-for nu, så dette vil helt tilstrækkeligt! Mange tak!
    Det er også muligt at tilsidesætte HTTPConnection._create_connection, der er til rådighed, da Python 2.7.7 og 3,5 på grund af bugs.python.org/issue7776.

    OriginalForfatteren MattH

  2. 17

    Andet (beskidt) måde, er abe-lappe socket.getaddrinfo.

    For eksempel denne kode tilføjer et (ubegrænset) cache til dns-opslag.

    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
    En fordel ved dette hack er også opfanger næsten alle dns-opslag i python, ikke kun via urlopen
    dette er en bedre løsning, hvis værter er scoped i et lille antal. jeg har en 10X hastigheden op med det. 🙂

    OriginalForfatteren Taha Jahangir

  3. 0

    Du bliver nødt til at gennemføre din egen dns-opslag kunde (eller bruger dnspython som du sagde). Det navn, opslag procedure i glibc er temmelig kompliceret at sikre kompatibilitet med andre ikke-dns-navn-systemer. Der er for eksempel ingen måde til at angive et bestemt DNS-server i glibc bibliotek.

    OriginalForfatteren speakman

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *