17

アドレスを解決するために(または)を使用するようにurllib2.urlopen(またはカスタムオープナー)に指示したいと思います。ただし、変更はしません。127.0.0.1::1/etc/resolv.conf

dnspython考えられる解決策の1つは、アドレスのクエリやhttplibカスタムURLオープナーの作成などのツールを使用することです。urlopenただし、カスタムネームサーバーを使用するように指示したいと思います。助言がありますか?

4

3 に答える 3

23

名前解決は最終的にはによって処理されるようsocket.create_connectionです。

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

「Host:」ヘッダーが設定されると、ホストを解決して、IPアドレスをオープナーに渡すことができます。

httplib.HTTPConnectionサブクラス化し、メソッドをラップしconnectて変更してから、self.hostに渡すことをお勧めしますsocket.create_connection

次に、サブクラスHTTPHandler(およびHTTPSHandler)を使用して、メソッドをhttplib独自のメソッドではなく自分自身をにhttp_open渡すメソッドに置き換えます。HTTPConnectiondo_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に入力する必要があります...

于 2010-02-10T13:24:10.497 に答える
22

別の(汚い)方法はモンキーパッチ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
于 2013-02-25T11:15:27.873 に答える
0

独自のDNSルックアップクライアントを実装する必要があります(またはあなたが言ったようにdnspythonを使用します)。glibcでの名前検索手順は、他のDNS以外の名前システムとの互換性を確保するために非常に複雑です。たとえば、glibcライブラリで特定のDNSサーバーを指定する方法はまったくありません。

于 2010-02-10T14:07:44.043 に答える