2015-07-21 3 views
2

Я не могу избежать максимальной глубины рекурсии Python RuntimeError с помощью BeautifulSoup.BeautifulSoup: RuntimeError: превышена максимальная глубина рекурсии

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

<div><code><code><code><code>Code in here</code></code></code></code></div> 

функцию я передаю мой объект суп является:

def _strip_descendent_code(self, soup): 
    sys.setrecursionlimit(2000) 
    # soup = BeautifulSoup(html, 'lxml') 
    for code in soup.findAll('code'): 
     s = "" 
     for c in code.descendents: 
      if not isinstance(c, NavigableString): 
       if c.name != code.name: 
        continue 
       elif c.name == code.name: 
        if isinstance(c, NavigableString): 
         s += str(c) 
        else: 
         continue 
     code.append(s) 
    return str(soup) 

Вы можете увидеть I Я пытаюсь увеличить лимит рекурсии по умолчанию, но это не решение. Я увеличился до такой степени, что C попадает на ограничение памяти на компьютере, а функция выше никогда не работает.

Любая помощь, чтобы заставить это работать и указать на ошибку, было бы очень полезно.

микропримесей повторы стека это:

File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1234, in find 
    l = self.find_all(name, attrs, recursive, text, 1, **kwargs) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1255, in find_all 
    return self._find_all(name, attrs, text, limit, generator, **kwargs) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 529, in _find_all 
    i = next(generator) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1269, in descendants 
    stopNode = self._last_descendant().next_element 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 284, in _last_descendant 
    if is_initialized and self.next_sibling: 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 997, in __getattr__ 
    return self.find(tag) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1234, in find 
    l = self.find_all(name, attrs, recursive, text, 1, **kwargs) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1255, in find_all 
    return self._find_all(name, attrs, text, limit, generator, **kwargs) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 529, in _find_all 
    i = next(generator) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1269, in descendants 
    stopNode = self._last_descendant().next_element 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 284, in _last_descendant 
    if is_initialized and self.next_sibling: 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 997, in __getattr__ 
    return self.find(tag) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1234, in find 
    l = self.find_all(name, attrs, recursive, text, 1, **kwargs) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1255, in find_all 
    return self._find_all(name, attrs, text, limit, generator, **kwargs) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 512, in _find_all 
    strainer = SoupStrainer(name, attrs, text, **kwargs) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1548, in __init__ 
    self.text = self._normalize_search_value(text) 
    File "/Users/almccann/.virtualenvs/evernoteghost/lib/python3.4/site-packages/bs4/element.py", line 1553, in _normalize_search_value 
    if (isinstance(value, str) or isinstance(value, collections.Callable) or hasattr(value, 'match') 
RuntimeError: maximum recursion depth exceeded while calling a Python object 
+0

Укажите, пожалуйста, точное сообщение об ошибке и трассировку стека. – dimo414

+0

Ошибка «RuntimeError: превышена максимальная глубина рекурсии при вызове объекта Python». Это выглядит как ошибка: http://bugs.python.org/issue1757057. Но я не уверен, как это исправить. – almccann

+0

Если эта ошибка является проблемой, решение должно просто состоять в обновлении вашей установки BeautifulSoup; он закрыт на три года. – dimo414

ответ

6

я столкнулся с этой проблемой и просматривали множество веб-страниц. Я приведу два метода для решения этой проблемы.

Однако, я думаю, мы должны знать, почему это произошло. Python ограничивает количество рекурсивных (номер по умолчанию - 1000). Мы можем видеть это число с print sys.getrecursionlimit(). Я думаю, что BeautifulSoup использует рекурсию для поиска дочерних элементов. Когда рекурсия более 1000 раз, появится RuntimeError: maximum recursion depth exceeded.

Первый способ: использование sys.setrecursionlimit() комплект ограниченное количество рекурсивных. Очевидно, вы можете установить 1000000, но, возможно, вызывать segmentation fault.

Второй способ:try-except. Если появилось maximum recursion depth exceeded, наш алгоритм может иметь проблемы. Вообще говоря, мы можем использовать циклы вместо рекурсии. В вашем вопросе мы можем иметь дело с HTML с replace() или регулярным выражением заранее.

И, наконец, приведу пример.

from bs4 import BeautifulSoup 
import sys 
#sys.setrecursionlimit(10000) 

try: 
    doc = ''.join(['<br>' for x in range(1000)]) 
    soup = BeautifulSoup(doc, 'html.parser') 
    a = soup.find('br') 
    for i in a: 
     print i 
except: 
    print 'failed' 

Если удалили #, он может печатать doc.

В надежде помочь вам.

Смежные вопросы