Regex для соответствия всем HTML-тэгам кроме <p> и </p>

Большинство ответов связаны с изменением вызова на json.dumps (), что не всегда возможно или желательно (это может произойти, например, в компоненте framework).

Если вы хотите быть в состоянии для вызова json.dumps (obj) как есть, тогда простое решение наследуется от dict:

class FileItem(dict):
    def __init__(self, fname):
        dict.__init__(self, fname=fname)

f = FileItem('tasks.txt')
json.dumps(f)  #No need to change anything here

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

22
задан Alan Moore 22 November 2009 в 09:16
поделиться

12 ответов

Я придумал это:

<(?!\/?p(?=>|\s.*>))\/?.*?>

x/
<           # Match open angle bracket
(?!         # Negative lookahead (Not matching and not consuming)
    \/?     # 0 or 1 /
    p           # p
    (?=     # Positive lookahead (Matching and not consuming)
    >       # > - No attributes
        |       # or
    \s      # whitespace
    .*      # anything up to 
    >       # close angle brackets - with attributes
    )           # close positive lookahead
)           # close negative lookahead
            # if we have got this far then we don't match
            # a p tag or closing p tag
            # with or without attributes
\/?         # optional close tag symbol (/)
.*?         # and anything up to
>           # first closing tag
/

Это будет теперь иметь дело с тегами p с или без атрибутов и закрытия p теги, но будет соответствовать пред и подобные теги, с или без атрибутов.

Это не разделяет атрибуты, но мои исходные данные не вставляет их. Я могу изменить это позже, чтобы сделать это, но это будет достаточно на данный момент.

11
ответ дан 29 November 2019 в 03:29
поделиться

Не уверенный, почему Вы желаете сделать, это - regex для санитизации HTML является не всегда лучшим методом (необходимо не забыть санировать атрибуты и такой, удалять JavaScript: hrefs и подобные)..., но, regex для соответствия HTML-тэгам, которые не являются <p></p>:

(<[^pP].*?>|</[^pP]>)

Подробный:

(
    <               # < opening tag
        [^pP].*?    # p non-p character, then non-greedy anything
    >               # > closing tag
|                   #   ....or....
    </              # </
        [^pP]       # a non-p tag
    >               # >
)
3
ответ дан 29 November 2019 в 03:29
поделиться

Если Вы настоите на использовании regex, то что-то вроде этого будет работать в большинстве случаев:

# Remove all HTML except "p" tags
$html =~ s{<(?>/?)(?:[^pP]|[pP][^\s>/])[^>]*>}{}g;

Объяснение:

s{
  <             # opening angled bracket
  (?>/?)        # ratchet past optional / 
  (?:
    [^pP]       # non-p tag
    |           # ...or...
    [pP][^\s>/] # longer tag that begins with p (e.g., <pre>)
  )
  [^>]*         # everything until closing angled bracket
  >             # closing angled bracket
 }{}gx; # replace with nothing, globally

, Но действительно, сохраните себя некоторые головные боли и используйте синтаксический анализатор вместо этого. CPAN имеет несколько модулей, которые подходят. Вот пример с помощью HTML:: модуль TokeParser , который идет с чрезвычайно способным HTML:: Синтаксический анализатор распределение CPAN:

use strict;

use HTML::TokeParser;

my $parser = HTML::TokeParser->new('/some/file.html')
  or die "Could not open /some/file.html - $!";

while(my $t = $parser->get_token)
{
  # Skip start or end tags that are not "p" tags
  next  if(($t->[0] eq 'S' || $t->[0] eq 'E') && lc $t->[1] ne 'p');

  # Print everything else normally (see HTML::TokeParser docs for explanation)
  if($t->[0] eq 'T')
  {
    print $t->[1];
  }
  else
  {
    print $t->[-1];
  }
}

HTML:: Синтаксический анализатор принимает вход в форме имени файла, открытого дескриптора файла или строки. Обертывание вышеупомянутого кода в библиотеке и создание настраивающегося места назначения (т.е. не всего print луг как в вышеупомянутом) не трудны. Результат будет намного более надежным, удобным в сопровождении, и возможно также быстрее (HTML:: Синтаксический анализатор использует бэкенд на базе С), чем попытка использовать регулярные выражения.

37
ответ дан 29 November 2019 в 03:29
поделиться

По-моему, попытка проанализировать HTML с чем-либо кроме синтаксического анализатора HTML просто просит мир боли. HTML действительно сложный язык (который является одной из основных причин, что XHTML был создан, который намного более прост, чем HTML).

, Например, это:

<HTML /
  <HEAD /
    <TITLE / > /
    <P / >

полный, 100%-й правильно построенный, 100%-й действительный документ HTML. (Ну, это пропускает объявление DOCTYPE, но кроме этого...)

Это семантически эквивалентно

<html>
  <head>
    <title>
      &gt;
    </title>
  </head>
  <body>
    <p>
      &gt;
    </p>
  </body>
</html>

, Но это - тем не менее, допустимый HTML, с которым Вы оказываетесь перед необходимостью иметь дело. Вы могли , конечно, создайте regex для парсинга его, но, как другие, уже предложенные, с помощью фактического синтаксического анализатора HTML, просто sooo намного легче.

16
ответ дан 29 November 2019 в 03:29
поделиться

Предположение, что это будет работать в Perl, как он делает на языках, которые утверждают, что использовали СОВМЕСТИМЫЙ С PERL синтаксис:

/<\/?[^p][^>]*>/

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

, Но это не будет соответствовать <pre> или <param> тег, к сожалению.

Это, возможно?

/<\/?(?!p>|p )[^>]+>/

, Который должен покрыть <p> теги, которые имеют атрибуты, также.

1
ответ дан 29 November 2019 в 03:29
поделиться

Вы также могли бы хотеть допускать пробел перед "p" в теге p. Не уверенный, как часто Вы столкнетесь с этим, но < p> является совершенно допустимым HTML.

1
ответ дан 29 November 2019 в 03:29
поделиться

, Так как HTML не является регулярным языком

, HTML не является всего лишь HTML-тэгами, и они могут быть adequatly, описанным регулярными выражениями.

2
ответ дан 29 November 2019 в 03:29
поделиться

Так как HTML не является регулярным языком, я не ожидал бы, что регулярное выражение сделает очень хорошее задание при соответствии ему. Они могли бы быть до этой задачи (хотя я не убежден), но я рассмотрел бы взгляд в другом месте; я уверен, что жемчуг должен иметь некоторые стандартные библиотеки для управления HTML.

Так или иначе, я думал бы, что то, чему Вы хотите соответствовать, является </? (p. + |.*) (\s*.*)> нежадно (я не знаю капризы regexp синтаксиса perl, таким образом, я не могу помочь далее). Я принимаю это, \s означает пробел. Возможно, это не делает. Так или иначе Вы хотите что-то, что это будет соответствовать смещению атрибутов с имени тега пробелом. Но это более трудно, чем это, поскольку люди часто помещают незавершенные угловые скобки в сценариях и комментариях и возможно даже заключенных в кавычки значениях атрибута, против которых Вы не хотите соответствовать.

Поэтому, как я говорю, я действительно не думаю, что regexps являются правильным инструментом для задания.

2
ответ дан 29 November 2019 в 03:29
поделиться

Попробуйте это, это должно работать:

/<\/?([^p](\s.+?)?|..+?)>/

Объяснение: это соответствует или одной букве кроме “p”, сопровождаемого дополнительным пробелом и большим количеством символов, или нескольким буквам (по крайней мере два).

РЕДАКТИРОВАНИЕ/: я добавил способность обработать атрибуты в p теги.

0
ответ дан 29 November 2019 в 03:29
поделиться

Исходный regex может быть сделан работать с очень небольшим усилием:

 <(?>/?)(?!p).+?>

проблема состояла в том что/? (или \?) бросил то, чему это соответствовало, когда утверждение после того, как это перестало работать. Используя группу неотслеживания в обратном порядке (?>...) вокруг этого заботится, что это никогда не выпускает подобранную наклонную черту, таким образом, (?! p) утверждение всегда привязывается на запуске текста тега.

(Который сказал, что я соглашаюсь, что обычно парсинг HTML с regexes не является способом пойти).

1
ответ дан 29 November 2019 в 03:29
поделиться

Необходимо, вероятно, также удалить любые атрибуты на < тег p>, так как кто-то плохо мог сделать что-то как:

<p onclick="document.location.href='http://www.evil.com'">Clickable text</p>

самый легкий способ сделать это, должен использовать regex людей, предлагают здесь искать & ltp> теги с атрибутами, и заменяют их < p> теги без атрибутов. Только быть на безопасной стороне.

-1
ответ дан 29 November 2019 в 03:29
поделиться

Я использовал Xetius regex и он отлично работает. За исключением некоторых flex-генерируемых тегов, которые могут быть :
без пробелов внутри. Я попытался исправить это простым ? после \s и похоже, что это работает :

<(?!\/?p(?=>|\s?.*>))\/?.*?>

Я использую его для очистки тегов из сгенерированного flex'ом html текста, поэтому я также добавил больше исключенных тегов :

<(?!\/?(p|a|b|i|u|br)(?=>|\s?.*>))\/?.*?>
3
ответ дан 29 November 2019 в 03:29
поделиться
Другие вопросы по тегам:

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