【问题标题】:subclassing beautifulsoup html parser, getting type error继承beautifulsoup html解析器,得到类型错误
【发布时间】:2011-10-07 08:33:53
【问题描述】:

我使用 beautifulsoup 编写了一个小包装器,很棒的 html 解析器

最近我尝试改进代码并使所有 beautifulsoup 方法直接在包装类中可用(而不是通过类属性),我认为将 beautifulsoup 解析器子类化是实现这一目标的最佳方法。

这是课程:

class ScrapeInputError(Exception):pass
from BeautifulSoup import BeautifulSoup

class Scrape(BeautifulSoup):
    """base class to be subclassed
    basically a subclassed BeautifulSoup wrapper that providers
    basic url fetching with urllib2
    and the basic html parsing with beautifulsoup
    and some basic cleaning of head,scripts etc'"""

    def __init__(self,file):
        self._file = file
        #very basic input validation
        import re
        if not re.search(r"^http://",self._file):
            raise ScrapeInputError,"please enter a url that starts with http://"

        import urllib2
        #from BeautifulSoup import BeautifulSoup
        self._page = urllib2.urlopen(self._file) #fetching the page
        BeautifulSoup.__init__(self,self._page)
        #self._soup = BeautifulSoup(self._page) #calling the html parser

这样我就可以开始上课了

x = Scrape("http://someurl.com")

并且能够使用 x.elem 或 x.find 遍历树

这对一些 beautifulsoup 方法(见上文)非常有效,但在其他方法中却失败了 - 那些使用迭代器的方法,如“for e in x:”

错误信息:

 Traceback (most recent call last):
  File "<pyshell#86>", line 2, in <module>
    print e
  File "C:\Python27\lib\idlelib\rpc.py", line 595, in __call__
    value = self.sockio.remotecall(self.oid, self.name, args, kwargs)
  File "C:\Python27\lib\idlelib\rpc.py", line 210, in remotecall
    seq = self.asynccall(oid, methodname, args, kwargs)
  File "C:\Python27\lib\idlelib\rpc.py", line 225, in asynccall
    self.putmessage((seq, request))
  File "C:\Python27\lib\idlelib\rpc.py", line 324, in putmessage
    s = pickle.dumps(message)
  File "C:\Python27\lib\copy_reg.py", line 77, in _reduce_ex
    raise TypeError("a class that defines __slots__ without "
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled

我研究了错误消息,但找不到任何我可以使用的东西 - 因为我不想玩 BeautifulSoup 的内部植入(老实说,我不知道或不理解 __slot____getstate__ ..) 我只是想使用这个功能。

我尝试从类的__init__ 返回一个beautifulsoup 对象,而不是子类化,但__init__ 方法返回None

很高兴在这里获得任何帮助。

【问题讨论】:

  • 旁注:不要使用re 来测试字符串是否以子字符串开头,这太过分了。请改用str.startswith()。 (if not file.startswith("http://"):)。
  • 另一个旁注:你真的要禁止https://吗? (或ftp://,或file://?)您可能希望依赖urlopen 自己的验证;它会在无效 URL 上引发 urllib2.URLError

标签: python beautifulsoup


【解决方案1】:

BeautifulSoup 代码中没有发生错误。相反,您的 IDLE 无法检索和打印该对象。请改用print str(e)


无论如何,在您的情况下子类 BeautifulSoup 可能不是最好的主意。你真的想继承所有的解析方法(如convert_charrefhandle_pierror)吗?更糟糕的是,如果您覆盖 BeautifulSoup 使用的东西,它可能会以一种难以找到的方式中断。

我不知道你的情况,但我建议preferring composition over inheritance(即在属性中有一个 BeautifulSoup 对象)。您可以轻松地(如果以一种有点 hacky 的方式)公开特定的方法,如下所示:

class Scrape(object):
    def __init__(self, ...):
        self.soup = ...
        ...
        self.find = self.soup.find

【讨论】:

  • 此方法是否也适用于 iterkey 方法?
  • No,但您仍然可以使用def __iter__(self): return iter(self.soup)
猜你喜欢
  • 2015-09-08
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 1970-01-01
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多