Удалите HTML-тэги не в позволенном списке от строки Python

Вместо этого

<i class="fa fa-user"></i>

Вы используете этот

<i class="fas fa-user"></i>

Вы должны удалить s из этого значка.

Вы дали ссылку на шрифт awesome 4 и использовали значок из шрифта awesome 5, поэтому он не работает. если вы даете шрифту 4 великолепных ссылки, вам нужно удалить s из этого значка, или же если вы не хотите удалять s из этого значка, так что вы должны использовать шрифт awesome 5 ссылок.

Это шрифт 5 классная ссылка.

 <link rel="stylesheet" 
 href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" 
 integrity="sha384- 
 fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" 
 crossorigin="anonymous">
67
задан davidism 4 February 2019 в 20:34
поделиться

4 ответа

Вот является использование простого решения BeautifulSoup:

from bs4 import BeautifulSoup

VALID_TAGS = ['strong', 'em', 'p', 'ul', 'li', 'br']

def sanitize_html(value):

    soup = BeautifulSoup(value)

    for tag in soup.findAll(True):
        if tag.name not in VALID_TAGS:
            tag.hidden = True

    return soup.renderContents()

Если Вы хотите удалить содержание недопустимых тегов также, замены tag.extract() для tag.hidden.

Вы могли бы также изучить использование lxml и Опрятный.

41
ответ дан Samarth Shah 24 November 2019 в 14:27
поделиться

Вышеуказанные решения с помощью Beautiful Soup работать не будут. Возможно, вы сможете взломать что-нибудь с Beautiful Soup выше и выше их, потому что Beautiful Soup обеспечивает доступ к дереву разбора. Через некоторое время, я думаю, я попытаюсь решить проблему правильно, но это недельный проект или около того, и у меня скоро не будет свободной недели.

Чтобы быть точным, не только Beautiful Soup будет генерировать исключения для некоторых ошибок синтаксического анализа, которые приведенный выше код не улавливает; но также существует множество очень реальных уязвимостей XSS, которые не обнаруживаются, например:

<<script>script> alert("Haha, I hacked your page."); </</script>script>

Вероятно, лучшее, что вы можете сделать, это вместо этого удалить элемент < как & lt; , чтобы запретить весь HTML, а затем использовать ограниченное подмножество, такое как Markdown, для правильного отображения форматирования. В частности, Вы также можете вернуться и повторно ввести общие фрагменты HTML с помощью регулярных выражений. Примерно так выглядит процесс:

_lt_     = re.compile('<')
_tc_ = '~(lt)~'   # or whatever, so long as markdown doesn't mangle it.     
_ok_ = re.compile(_tc_ + '(/?(?:u|b|i|em|strong|sup|sub|p|br|q|blockquote|code))>', re.I)
_sqrt_ = re.compile(_tc_ + 'sqrt>', re.I)     #just to give an example of extending
_endsqrt_ = re.compile(_tc_ + '/sqrt>', re.I) #html syntax with your own elements.
_tcre_ = re.compile(_tc_)

def sanitize(text):
    text = _lt_.sub(_tc_, text)
    text = markdown(text)
    text = _ok_.sub(r'<\1>', text)
    text = _sqrt_.sub(r'&radic;<span style="text-decoration:overline;">', text)
    text = _endsqrt_.sub(r'</span>', text)
    return _tcre_.sub('&lt;', text)

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

37
ответ дан 24 November 2019 в 14:27
поделиться

Вот что я использую в своем собственном проекте. Приемлемые атрибуты / атрибуты получены из feedparser , и BeautifulSoup выполняет эту работу.

from BeautifulSoup import BeautifulSoup

acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area', 'b', 'big',
      'blockquote', 'br', 'button', 'caption', 'center', 'cite', 'code', 'col',
      'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em',
      'font', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 
      'ins', 'kbd', 'label', 'legend', 'li', 'map', 'menu', 'ol', 
      'p', 'pre', 'q', 's', 'samp', 'small', 'span', 'strike',
      'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th',
      'thead', 'tr', 'tt', 'u', 'ul', 'var']

acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey',
  'action', 'align', 'alt', 'axis', 'border', 'cellpadding', 'cellspacing',
  'char', 'charoff', 'charset', 'checked', 'cite', 'clear', 'cols',
  'colspan', 'color', 'compact', 'coords', 'datetime', 'dir', 
  'enctype', 'for', 'headers', 'height', 'href', 'hreflang', 'hspace',
  'id', 'ismap', 'label', 'lang', 'longdesc', 'maxlength', 'method',
  'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'prompt', 
  'rel', 'rev', 'rows', 'rowspan', 'rules', 'scope', 'shape', 'size',
  'span', 'src', 'start', 'summary', 'tabindex', 'target', 'title', 'type',
  'usemap', 'valign', 'value', 'vspace', 'width']

def clean_html( fragment ):
    while True:
        soup = BeautifulSoup( fragment )
        removed = False        
        for tag in soup.findAll(True): # find all tags
            if tag.name not in acceptable_elements:
                tag.extract() # remove the bad ones
                removed = True
            else: # it might have bad attributes
                # a better way to get all attributes?
                for attr in tag._getAttrMap().keys():
                    if attr not in acceptable_attributes:
                        del tag[attr]

        # turn it back to html
        fragment = unicode(soup)

        if removed:
            # we removed tags and tricky can could exploit that!
            # we need to reparse the html until it stops changing
            continue # next round

        return fragment

Некоторые небольшие тесты, чтобы убедиться, что это работает правильно:

tests = [   #text should work
            ('<p>this is text</p>but this too', '<p>this is text</p>but this too'),
            # make sure we cant exploit removal of tags
            ('<<script></script>script> alert("Haha, I hacked your page."); <<script></script>/script>', ''),
            # try the same trick with attributes, gives an Exception
            ('<div on<script></script>load="alert("Haha, I hacked your page.");">1</div>',  Exception),
             # no tags should be skipped
            ('<script>bad</script><script>bad</script><script>bad</script>', ''),
            # leave valid tags but remove bad attributes
            ('<a href="good" onload="bad" onclick="bad" alt="good">1</div>', '<a href="good" alt="good">1</a>'),
]

for text, out in tests:
    try:
        res = clean_html(text)
        assert res == out, "%s => %s != %s" % (text, res, out)
    except out, e:
        assert isinstance(e, out), "Wrong exception %r" % e
25
ответ дан 24 November 2019 в 14:27
поделиться

Используйте lxml.html.clean ! Это очень легко!

from lxml.html.clean import clean_html
print clean_html(html)

Предположим, следующий html:

html = '''\
<html>
 <head>
   <script type="text/javascript" src="evil-site"></script>
   <link rel="alternate" type="text/rss" src="evil-rss">
   <style>
     body {background-image: url(javascript:do_evil)};
     div {color: expression(evil)};
   </style>
 </head>
 <body onload="evil_function()">
    <!-- I am interpreted for EVIL! -->
   <a href="javascript:evil_function()">a link</a>
   <a href="#" onclick="evil_function()">another link</a>
   <p onclick="evil_function()">a paragraph</p>
   <div style="display: none">secret EVIL!</div>
   <object> of EVIL! </object>
   <iframe src="evil-site"></iframe>
   <form action="evil-site">
     Password: <input type="password" name="password">
   </form>
   <blink>annoying EVIL!</blink>
   <a href="evil-site">spam spam SPAM!</a>
   <image src="evil!">
 </body>
</html>'''

Результаты ...

<html>
  <body>
    <div>
      <style>/* deleted */</style>
      <a href="">a link</a>
      <a href="#">another link</a>
      <p>a paragraph</p>
      <div>secret EVIL!</div>
      of EVIL!
      Password:
      annoying EVIL!
      <a href="evil-site">spam spam SPAM!</a>
      <img src="evil!">
    </div>
  </body>
</html>

Вы можете настроить элементы, которые хотите очистить, и еще много чего.

57
ответ дан 24 November 2019 в 14:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: