2012-11-09 25 views
1

我正在編寫一個腳本,用於從文章中提取內容並刪除任何不必要的內容,例如。腳本和樣式。美麗的湯不斷提高以下異常:美麗的湯錯誤:'<class'bs4.element.Tag'>'對象沒有屬性'內容'?

'<class 'bs4.element.Tag'>' object has no attribute 'contents' 

這裏的裝飾功能的代碼(元素是一個包含網頁的內容中的HTML元素):

def trim(element): 
    elements_to_remove = ('script', 'style', 'link', 'form', 'object', 'iframe') 
    for i in elements_to_remove: 
     remove_all_elements(element, i) 

    attributes_to_remove = ('class', 'id', 'style') 
    for i in attributes_to_remove: 
     remove_all_attributes(element, i) 

    remove_all_comments(element) 

    # Remove divs that have more non-p elements than p elements 
    for div in element.find_all('div'): 
     p = len(div.find_all('p')) 
     img = len(div.find_all('img')) 
     li = len(div.find_all('li')) 
     a = len(div.find_all('a')) 

     if p == 0 or img > p or li > p or a > p: 
      div.decompose() 

看着堆棧跟蹤,這個問題似乎從這個方法來正確後的聲明:

# Remove divs that have more non-p elements than p elements 
    for div in element.find_all('div'): 
     p = len(div.find_all('p')) # <-- div.find_all('p') 

我不知道爲什麼bs4.element.Tag的這個實例沒有屬性「內容」?我嘗試了一下在實際網頁和元素充滿了P公司和IMG的的...

這裏的回溯(這是一個Django項目我工作的一部分):

Environment: 


Request Method: POST 
Request URL: http://localhost:8000/read/add/ 

Django Version: 1.4.1 
Python Version: 2.7.3 
Installed Applications: 
('django.contrib.auth', 
'django.contrib.contenttypes', 
'django.contrib.sessions', 
'django.contrib.sites', 
'django.contrib.messages', 
'django.contrib.staticfiles', 
'home', 
'account', 
'read', 
'review') 
Installed Middleware: 
('django.middleware.common.CommonMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 
'django.middleware.csrf.CsrfViewMiddleware', 
'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.messages.middleware.MessageMiddleware') 


Traceback: 
File "/home/marco/.virtualenvs/sandra/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 
    111.       response = callback(request, *callback_args, **callback_kwargs) 
File "/home/marco/sandra/read/views.py" in add 
    24.    Article.objects.create_article(request.user, url) 
File "/home/marco/sandra/read/models.py" in create_article 
    11.   title, content = logic.process_html(web_page.read()) 
File "/home/marco/sandra/read/logic.py" in process_html 
    7.  soup = htmlbarber.give_haircut(BeautifulSoup(html_code, 'html5lib')) 
File "/home/marco/sandra/read/htmlbarber/__init__.py" in give_haircut 
    45.  scissor.trim(element) 
File "/home/marco/sandra/read/htmlbarber/scissor.py" in trim 
    35.   p = len(div.find_all('p')) 
File "/home/marco/.virtualenvs/sandra/local/lib/python2.7/site-packages/bs4/element.py" in find_all 
    1128.   return self._find_all(name, attrs, text, limit, generator, **kwargs) 
File "/home/marco/.virtualenvs/sandra/local/lib/python2.7/site-packages/bs4/element.py" in _find_all 
    413.     return [element for element in generator 
File "/home/marco/.virtualenvs/sandra/local/lib/python2.7/site-packages/bs4/element.py" in descendants 
    1140.   if not len(self.contents): 
File "/home/marco/.virtualenvs/sandra/local/lib/python2.7/site-packages/bs4/element.py" in __getattr__ 
    924.    "'%s' object has no attribute '%s'" % (self.__class__, tag)) 

Exception Type: AttributeError at /read/add/ 
Exception Value: '<class 'bs4.element.Tag'>' object has no attribute 'contents' 

這裏的的remove_all_ *函數的源代碼:

def remove_all_elements(element_to_clean, unwanted_element_name): 
    for to_remove in element_to_clean.find_all(unwanted_element_name): 
     to_remove.decompose() 

def remove_all_attributes(element_to_clean, unwanted_attribute_name): 
    for to_inspect in [element_to_clean] + element_to_clean.find_all(): 
     try: 
      del to_inspect[unwanted_attribute_name] 
     except KeyError: 
      pass 

def remove_all_comments(element_to_clean): 
    for comment in element_to_clean.find_all(text=lambda text:isinstance(text, Comment)): 
     comment.extract() 
+0

這很奇怪。如果您發佈了完整的追蹤信息,這將有所幫助。 – Iguananaut

+0

您可能需要對for循環中的所有'remove_all_elements'調用進行求和。它不會解決當前的問題,但它會增強代碼的可讀性。 – iTayb

+0

@iTayb感謝提示:) –

回答

1

我認爲問題是,在remove_all_elements或者在你的代碼別的地方要刪除你的一些標籤的contents屬性。

看起來像是在您撥打to_remove.decompose()時發生這種情況。下面是該方法的源:

def decompose(self): 
    """Recursively destroys the contents of this tree.""" 
    self.extract() 
    i = self 
    while i is not None: 
     next = i.next_element 
     i.__dict__.clear() 
     i = next 

這裏,如果你調用這個函數手動發生了什麼:

>> soup = BeautifulSoup('<div><p>hi</p></div>') 
>>> d0 = soup.find_all('div')[0] 
>>> d0 
<div><p>hi</p></div> 
>>> d0.decompose() 
>>> d0 
Traceback (most recent call last): 
... 
Traceback (most recent call last): 
AttributeError: '<class 'bs4.element.Tag'>' object has no attribute 'contents' 

看來,一旦在一個標籤叫decompose你不應該試圖使用該標籤再次。我不太確定這是怎麼發生的。

有一件事我會嘗試檢查是len(element.__dict__) > 0在您的trim()函數中的所有時間。

+0

我不確定,我使用del語句的唯一地方是del to_inspect [unwanted_attribute_name]。 –

+0

我註釋掉了所有remove_all_ *函數,但它仍然不起作用。然後,我取消了所有的註釋,並用p = 99替換了p = len(div.find_all('p')),而且令人驚訝的是,它停止了拋出異常! :OI發現奇怪的... –

+0

我用div.extract()替換了div.decompose()並且它工作了:)可能是因爲div在for語句中被定義爲element.find_all的當前元素的別名'div')和'分解'div導致這些問題? –