2010-11-23 3 views
3

それはXML parsers often send out HTTP requests for fetching DTDsが文書で参照既知の問題です。具体的には、Python's one does this。これにより、多くのこれらのDTDをホストするwww.w3.orgのトラフィックが過剰になります。これにより、XML解析は非常に時間がかかり、場合によってはタイムアウトになります。これは、信頼できないサードパーティに依存しているテキスト処理に関連しているように見えるため、重大な問題になる可能性があります。xml.saxでDTDリクエストにHTTPプロキシを使用させるにはどうすればよいですか?

(真の解決策は非常に困難であるため)、この問題を軽減するために、私はローカルにキャッシュするWebプロキシをインストールし、このプロキシを経由してその要求を送信するxml.saxをお願いしたいと思います。私は具体的には、プロキシ設定が他のコンポーネントに漏れることを望まないので、システム全体の設定は問題になりません。

にはどうすればxml.saxは、HTTPプロキシを使用することができますか?

私が持っている:

handler = # instance of a subclass of xml.sax.handler.ContentHandler 

parser = xml.sax.make_parser() 
parser.setContentHandler(handler) 
parser.parse(indata) 
return handler.result() 

一つのアプローチは、カスタムのEntityResolverを使用することです。ただし、十分な情報が得られないため、it is not possible to implement a caching EntityResolverが表示されます。これを行うには

+0

バージョンは何? – aaronasterling

+0

@aaronasterling:2.5が好ましいが、2.6および2.7も許容されます。 –

答えて

2

一つの迅速かつ汚い方法は、モンキーパッチsaxutils.prepare_input_sourceになります。あなたはかなりそれを貼り付け、プロキシがインストールされていることがurllib2からUrlOpenerを取得するようにurllib.urlopenを呼び出す枝を微調整+コピーすることができます。

残念ながら、これはシステム全体の設定を変更したり、結果をキャッシュする独自のEntityResolverを作成せずに文字通りの動作を得ることができる唯一の方法だと思います。

は明らかにurllib.urlopenを呼び出し、この動作を変更するオプションはありません。だから、あなたのプロキシを経由しなければならないでしょう。それはurllibの他のすべてのクライアントに影響します。

マグナスホフことで

作業猿パッチング実装:パイソンの

def make_caching_prepare_input_source(old_prepare_input_source, proxy): 
    def caching_prepare_input_source(source, base = None): 
     if isinstance(source, xmlreader.InputSource): 
      return source 

     full_uri = urlparse.urljoin(base or "", source) 

     if not full_uri.startswith('http:'): 
      args = (source,) if base == None else (source, base) 
      return old_prepare_input_source(*args) 

     r = urllib2.Request(full_uri) 
     r.set_proxy(proxy, 'http') 
     f = urllib2.urlopen(r) 

     i = xmlreader.InputSource() 
     i.setSystemId(source) 
     i.setByteStream(f) 

     return i 

    return caching_prepare_input_source 

def enable_http_proxy(server): 
    saxutils.prepare_input_source = make_caching_prepare_input_source(
     saxutils.prepare_input_source, 
     server, 
    ) 
+0

うーん...本当ですか? Python 2.5.1では、エンティティは 'expat.c'の中で深く解決され、' urlopen'はソースのためだけに呼び出されます。 – khachik

+0

@khachik。はい、ソースを取得することはすべて問題です。キャッシュされている場合(プロキシ経由でルーティングされる)、目的が達成されます。または私は何かを逃していますか? – aaronasterling

+0

私はEntityResolverに取り組んでいますので、その方向性についての洞察も歓迎します:)明らかに、私は 'saxutils.prepare_input_source'に含まれる' base'引数を取得しません。 –

関連する問題