создание подклассов красивого парсера html, получение ошибки типа - PullRequest
3 голосов
/ 07 октября 2011

Я написал небольшую оболочку, используя прекрасный HTML-парсер beautifulsoup

, недавно я попытался улучшить код и сделать все методы 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 (см. выше), но не с другими - теми, которые используют итератор типа «для e в 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__ ..) Я просто хочу использовать функциональность.

вместо подклассов я попытался вернуть beautifобъект ulsoup из __init__ класса, но метод __init__ возвращает None

Буду рад любой помощи здесь.

1 Ответ

1 голос
/ 07 октября 2011

Ошибка не происходит в коде BeautifulSoup.Скорее, ваш IDLE не может получить и распечатать объект.Вместо этого попробуйте print str(e).


В любом случае, создание подкласса BeautifulSoup в вашей ситуации может оказаться не лучшей идеей.Вы действительно хотите наследовать все методы синтаксического анализа (например, convert_charref, handle_pi или error)?Хуже того, если вы переопределите что-то, что использует BeautifulSoup, оно может быть трудно найти.

Я не знаю вашей ситуации, но я предлагаю , предпочитая композицию наследованию (т.е. наличие объекта BeautifulSoup в атрибуте).Вы можете легко (если немного хакерски) раскрыть определенные методы, такие как:

class Scrape(object):
    def __init__(self, ...):
        self.soup = ...
        ...
        self.find = self.soup.find
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...