Разбор документа с BeautifulSoup без разбора содержимого тегов <code> - PullRequest
10 голосов
/ 24 октября 2010

Я пишу приложение для блога с Django.Я хочу разрешить авторам комментариев использовать некоторые теги (например, <strong>, a и т. Д.), Но отключить все остальные.

Кроме того, я хочу разрешить им вставлять код в tags, and have pygments parse them.</p> <p>For example, someone might write this comment:</p> <pre><code>I like this article, but the third code example <em>could have been simpler</em>: <code lang="c"> #include <stdbool.h> #include <stdio.h> int main() { printf("Hello World\n"); }

Проблема в том, что когда я анализирую комментарий с BeautifulSoup, чтобы удалить запрещенные теги HTML, он также анализирует внутреннюю часть блоков и обрабатываета такжекак если бы они были тегами HTML.

Как я могу сказать BeautifulSoup не анализировать блоки ?Может быть, есть другие парсеры HTML лучше для этой работы?

Ответы [ 5 ]

1 голос
/ 24 октября 2010

С Python wiki

>>>import cgi
>>>cgi.escape("<string.h>")
>>>'&lt;string.h&gt;'

>>>BeautifulSoup('&lt;string.h&gt;', 
...               convertEntities=BeautifulSoup.HTML_ENTITIES)
1 голос
/ 24 октября 2010

Проблема в том, что <code> обрабатывается в соответствии с обычными правилами для разметки HTML, а содержимое внутри тегов <code> по-прежнему является HTML (теги существуют главным образом для управления форматированием CSS, а не для изменения правил анализа).

То, что вы пытаетесь сделать, - это создать другой язык разметки, который очень похож, но не идентичен HTML.Простым решением было бы предположить, что определенные правила, такие как «<code> и должны появляться в строке сами по себе», и выполнить некоторую предварительную обработку самостоятельно.

  1. Очень простой - хотя и не на 100% надежный - метод заключается в замене ^<code>$ на <code><![CDATA[ и ^ $ на ]]>.Это не совсем надежно, потому что, если блок кода содержит ]]>, все пойдет ужасно неправильно.
  2. Более безопасный вариант - заменить опасные символы внутри блоков кода (<, > и &, вероятно, достаточно) с их эквивалентными символьными ссылками на сущности (&lt;, &gt; и &amp;).Вы можете сделать это, передав каждый идентифицированный вами блок кода в cgi.escape(code_block).

После завершения предварительной обработки отправьте результат в BeautifulSoup как обычно.

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

Если элемент <code> содержит неэкранированные символы <, &, > внутри кода, то это недопустимый HTML-код.BeautifulSoup попытается преобразовать его в действительный HTML.Возможно, это не то, что вам нужно.

Чтобы преобразовать текст в действительный HTML, вы можете адаптировать регулярное выражение, которое убирает теги из HTML , чтобы извлечь текст из блока <code> изамените его на cgi.escape() версию.Должно работать нормально, если нет вложенных тегов <code>.После этого вы можете перевести продезинфицированный html на BeautifulSoup.

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

РЕДАКТИРОВАТЬ:

Используйте python-markdown2 для обработки ввода и попросите пользователей сделать отступ в областях кода.

>>> print html
I like this article, but the third code example <em>could have been simpler</em>:

    #include <stdbool.h>
    #include <stdio.h>

    int main()
    {
        printf("Hello World\n");
    }

>>> import markdown2
>>> marked = markdown2.markdown(html)
>>> marked
u'<p>I like this article, but the third code example <em>could have been simpler</em>:</p>\n\n<pre><code>#include &lt;stdbool.h&gt;\n#include &lt;stdio.h&gt;\n\nint main()\n{\n    printf("Hello World\\n");\n}\n
\ n '>>> печать помечена

Мне нравится эта статья, но третий пример кода мог бы быть проще :

#include &lt;stdbool.h&gt;
#include &lt;stdio.h&gt;

int main()
{
    printf("Hello World\n");
}

Если вам все еще нужно перемещаться и редактировать его с BeautifulSoup, сделайтематериал ниже.Включите преобразование сущностей, если вам нужно вставить «<» и «>» (вместо «<» и «>»).

soup = BeautifulSoup(marked, 
                     convertEntities=BeautifulSoup.HTML_ENTITIES)
>>> soup
<p>I like this article, but the third code example <em>could have been simpler</em>:</p>
<pre><code>#include <stdbool.h>
#include <stdio.h>

int main()
{
    printf("Hello World\n");
}
def загущенный (суп): "" " blah blah <entity> blah blah " "" codez = soup.findAll ('code') # получить теги кода для кода в codez: # взять все содержимое внутри кодатеги и преобразовать их в одну строку escape_me = '' .join ([k .__ str __ () для k в code.contents]) escaped = cgi.escape (escape_me) # экранировать их с помощью cgi code.replaceWith ('%s '% escaped) # replace Объекты Tag на экранированную строку возвращают суп
0 голосов
/ 24 октября 2010

К сожалению, BeautifulSoup не может быть заблокирован для анализа блоков кода.

Одно из решений, которое вы хотите достичь, это тоже

1) Снять блоки кода

soup = BeautifulSoup(unicode(content))
code_blocks = soup.findAll(u'code')
for block in code_blocks:
    block.replaceWith(u'<code class="removed"></code>')

2) Выполните обычный анализ для удаления недопустимых тегов.

3) Повторно вставьте блоки кода и заново сгенерируйте HTML.

stripped_code = stripped_soup.findAll(u"code", u"removed")
# re-insert pygment formatted code

Я бы ответил с некоторым кодом, но недавно я прочитал блог, который делает это элегантно.

...