10

Python rawdog RSS リーダー ライブラリと BeautifulSoup ウェブスクレイピング ライブラリの機能を組み合わせるコードを書いています。私が克服しようとしている内臓のどこかに葛藤があります。

この単純化されたコードで問題を再現できます。

    import sys, gzip
    def scrape(filename):
        contents = gzip.open(filename,'rb').read()
        contents = contents.decode('utf-8','replace')
        import BeautifulSoup as BS
        print 'before rawdog: ', len(BS.BeautifulSoup(contents)) # prints 4, correct answer
        from rawdoglib import rawdog as rd
        print 'after rawdog: ', len(BS.BeautifulSoup(contents)) # prints 3, incorrect answer

インポートの順序や場所は関係ありません。rawdog をインポートすると、常に BS.BeautifulSoup() メソッドが間違った応答を返します。BeautifulSoup が必要になる頃には rawdog はもう必要ないので、その時点でパッケージを削除しようとしましたが、BS はまだ壊れています。私が試したがうまくいかなかった修正:

  • rawdog コードが独自に BeautifulSoup をインポートしていることに気付きました。だから私import BeautifulSoupはrawdogコードから削除してrawdogを再インストールしようとしました
  • BeautifulSoup をインポートする前に rawdog モジュールを削除します。
    • for x in filter(lambda y: y.startswith('rawdog'), sys.modules.keys()): del sys.modules[x]
  • rawdog からより具体的なクラス/メソッドをインポートします。from rawdoglib.rawdog import FeedState
  • rawdog をインポートする前後に、問題のメソッドに新しい名前を付けます。from BeautifulSoup import BeautifulSoup as BS
  • from __future__ import absolute_import

rawdog が名前空間にインポートされたことがある場合、私は常に len(BeautifulSoup(contents)) == 3 を取得します。両方のパッケージは複雑すぎて、問題の重複が何であるかを正確に把握することができませんでした.dir(BeautifulSoup)とdir(を検索する以外に、それを把握するためにどのツールを使用すればよいかわかりません. rawdog)、良い手がかりが見つかりませんでした。

更新、回答への対応:すべての入力ファイルで問題が発生するわけではないことを省略しました。これは非常に重要です。申し訳ありません。問題のあるファイルは非常に大きいため、ここに投稿できないと思います。良いファイルと悪いファイルの決定的な違いを見つけ出して投稿します。これまでのデバッグのヘルプに感謝します。

さらにデバッグ!入力テキストのこのブロックを問題があると特定しました。

    function SwitchMenu(obj){
      if(document.getElementById){
      var el = document.getElementById(obj);
      var ar = document.getElementById("masterdiv").getElementsByTagName("span"); //DynamicDrive.com change
         if(el.style.display != "block"){ //DynamicDrive.com change
         for (var i=0; i<ar.length; i++){
            if (ar[i].className=="submenu") //DynamicDrive.com change
            ar[i].style.display = "none";
      }
      el.style.display = "block";
      }else{
        el.style.display = "none";
    }
}

}

このブロックをコメントアウトすると、rawdog インポートの有無にかかわらず、BeautifulSoup を介して正しい解析が得られます。ブロックでは、rawdog + BeautifulSoup に障害があります。このようなブロックの入力を検索する必要がありますか、それともより良い回避策がありますか?

4

3 に答える 3

5

のバグですrawdoglib.feedparser.pyrawdogモンキーパッチsmglibです:198行目で次のようになっています。

if sgmllib.endbracket.search(' <').start(0):
    class EndBracketMatch:
        endbracket = re.compile('''([^'"<>]|"[^"]*"(?=>|/|\s|\w+=)|'[^']*'(?=>|/|\s|\w+=))*(?=[<>])|.*?(?=[<>])''')
        def search(self,string,index=0):
            self.match = self.endbracket.match(string,index)
            if self.match: return self
        def start(self,n):
            return self.match.end(n)
    sgmllib.endbracket = EndBracketMatch()

これは、エラーを再現するためのスクリプトです。

contents = '''<a><ar "none";                                                 
</a> '''                                                                     
import BeautifulSoup as BS                                                   
print 'before rawdog: ', len(BS.BeautifulSoup(contents)) # prints 4, correct answer
from rawdoglib import rawdog as rd                                           
print 'after rawdog: ', len(BS.BeautifulSoup(contents)) # prints 3, incorrect

「a」タグ内の「<」で壊れます。OPのスニペットでは、次の行によってトリガーされます:( for (var i=0; i<ar.length; i++){「<」文字に注意してください)。

rawdogのMLで提出された問題:http://lists.us-lot.org/pipermail/rawdog-users/2012-August/000327.html

于 2012-08-14T10:10:34.637 に答える
0

あなたが抱えている問題はimports;の連鎖だと思います。BSパッケージをインポートしている 2 つの異なる場所が競合していること。

このスレッドは、必要なものかもしれません。

(あと、BSパッケージって真面目な文脈で言えるのもすごいですよね。)

于 2012-08-13T17:41:06.103 に答える
0

rawdog がインポートせずにバグを引き起こす可能性がある場合BeautifulSoup(間接的にインポートされていないことを確認したと思いますか?)、何らかの方法で矛盾して読み込まれる共有依存関係が必要です。しかし、問題はモンキー パッチである必要はありません。同じライブラリの異なるバージョンをロードすると、一貫性のない動作が発生する可能性があります。たとえば、そのうちの 1 つが特別なインポート パスを使用している場合、トップレベル モジュールの独自のバージョンを提供している場合、または次のようなコードを持っている場合:

try: 
    import ElementPath 
except ImportError: 
    ElementPath = _SimpleElementPath()

これが問題かどうかを確認するには、次のことを試してください:BeautifulSoup単独でロードし、他には何もロードせず、モジュールとその場所のリストをダンプします。

import BeautifulSoup
import sys
sys.stdout = open("soup-modules.txt", "w")
for k,v in sorted(sys.modules.items()):
    if v:
        print k, v.__dict__.get('__file__')

次に、rawdog で同じことを行い、出力を比較します。同じ名前で別の起源を持つモジュールが表示された場合、それが原因である可能性があります。

于 2012-08-14T10:28:22.610 に答える