2015-03-06 5 views
2

Я пытаюсь использовать весь текст (видимый пользователем) в HTML-файле. Вот очевидная вещь:Настройка всего текста в дереве DOM с помощью BeautifulSoup

from bs4 import BeautifulSoup 

def upcaseAll(str): 
    soup = BeautifulSoup(str) 
    for tag in soup.find_all(True): 
     for s in tag.strings: 
      s.replace_with(unicode(s).upper()) 
    return unicode(soup) 

Это происходит сбой:

File "/Users/malvolio/flip.py", line 23, in upcaseAll 
    for s in tag.strings: 
    File "/Library/Python/2.7/site-packages/bs4/element.py", line 827, in _all_strings 
    for descendant in self.descendants: 
    File "/Library/Python/2.7/site-packages/bs4/element.py", line 1198, in descendants 
    current = current.next_element 
AttributeError: 'NoneType' object has no attribute 'next_element' 

Все варианты я могу думать о аварии точно так же. BS4, похоже, не нравится, когда я заменяю много NavigableStrings. Как я могу это сделать?

+0

Как насчет использования 'find_all (text = True)' вместо этого? – alecxe

ответ

2

Вы не должны использовать str как аргумент функции, так как это теневое имя встроенного python.

Кроме того, вы должны быть в состоянии преобразовать видимые элементы только с помощью prettify с форматировщиком так:

... 
return soup.prettify(formatter=lambda x: unicode(x).upper()) 

Я испытал сейчас, и это работает:

from bs4 import BeautifulSoup 

import requests 

r = requests.get('http://www.stackoverflow.com') 

soup = BeautifulSoup(r.content) 

print soup.prettify(formatter=lambda x: unicode(x).upper())[:200] 
<!DOCTYPE html> 
<html> 
<head> 
    <title> 
    STACK OVERFLOW 
    </title> 
    <link href="//CDN.SSTATIC.NET/STACKOVERFLOW/IMG/FAVICON.ICO?V=00A326F96F68" rel="SHORTCUT ICON"/> 
    <link href="//CDN.SSTATIC.NE 
    ... 

Вы можете прочитать OUTPUT FORMATTER для получения более подробной информации.

Надеюсь, это поможет.

+1

Я хочу отметить, что в документации, на которую вы указываете ... использует 'str' как имя параметра. – Malvolio

+0

@Malvolio, очень хорошее место на самом деле ... и я считаю, что они совершили ошибку там :) – Anzel

+0

@Malvolio, на самом деле мне нужно исправить мой вышеприведенный комментарий. Я только что посмотрел на ** bs4 ** исходный код, это не ошибка, а очень умный способ реализовать это. ** formatter ** сначала проверит, прошел ли переданный параметр * CALLABLE * - ** str **, так что ** lambda **, и в своем примере они гибко переопределяют ** str ** для возврата ** str.upper (...) ** для достижения преобразования в верхний регистр. – Anzel

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