10

我正在编写代码来组合来自 python rawdog RSS 阅读器库和 BeautifulSoup webscraping 库的函数。我正在努力克服内心的某个地方的冲突。

我可以用这个简化的代码复制这个问题:

    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.py. rawdog是猴子补丁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包的两个不同位置存在冲突。

那么,这个线程可能是您所需要的。

(另外,BS在严肃的语境中,包装是一件很棒的事情。)

于 2012-08-13T17:41:06.103 回答
0

如果 rawdog 可以在不导入的情况下触发错误BeautifulSoup(我认为您已经检查过它不是间接导入的?),那么它们必须具有以某种方式加载不一致的共享依赖项。但问题不一定是猴子补丁:如果他们加载同一个库的不同版本,你可能会得到不一致的行为。例如,如果其中一个使用特殊的导入路径,提供自己的顶级模块版本,或者具有如下代码:

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 回答