С задачей очистки html от лишних тегов сталкиваются абсолютно все.
Первое, что приходит на ум, это использовать php-функцию strip_tags():
string strip_tags (string str [, string allowable_tags])
Функция возвращает строку, очищенную от тегов. В качестве аргумента
allowable_tags передаются теги, которые
не надо удалять. Функция работает, но, мягко говоря, неидеально. По ходу, там нет проверки на валидность кода, что может повлечь за собой удаление текста, не входящего в тэги.
Инициативные разработчики сложа руки не сидели — в сети можно найти доработанные функции. Хорошим примером является
strip_tags_smart.
Применять или не применять готовые решения — личный выбор программиста. Так сложилось, что мне чаще всего не требуется "универсального" обработчика и бывает удобнее почистить код регулярками.
От чего зависит выбор того или иного способа обработки?
1. От исходного материала и сложности его анализа.Если вам нужно обрабатывать достаточно простые htmp-тексты, без какой-либо навороченной верстки, ясные, как день :), то можно использовать стандартные функции.
Если в текстах есть определенные особенности, которые надо учесть, то тут-то и пишутся специальные обработчики. В одних может использоваться просто
str_replace. Например:
$s = array('’' => '’', // Right-apostrophe (eg in I'm)
'“' => '“', // Opening speech mark
'–' => '—', // Long dash
'â€' => '”', // Closing speech mark
'é' => 'é', // e acute accent
chr(226) . chr(128) . chr(153) => '’', // Right-apostrophe again
chr(226) . chr(128) . chr(147) => '—', // Long dash again
chr(226) . chr(128) . chr(156) => '“', // Opening speech mark
chr(226) . chr(128) . chr(148) => '—', // M dash again
chr(226) . chr(128) => '”', // Right speech mark
chr(195) . chr(169) => 'é', // e acute again
);
foreach ($s as $needle => $replace)
{
$htmlText = str_replace($needle, $replace, $htmlText);
}
Другие могут быть основаны на
регулярных выражениях. Как пример:
function getTextFromHTML($htmlText)
{
$search = array ("'<script[^>]*?>.*?</script>'si", // Remove javaScript
"'<style[^>]*?>.*?</style>'si", // Remove styles
"'<xml[^>]*?>.*?</xml>'si", // Remove xml tags
"'<[\/\!]*?[^<>]*?>'si", // Remove HTML-tags
"'([\r\n])[\s] '", // Remove spaces
"'&(quot|#34);'i", // Replace HTML special chars
"'&(amp|#38);'i",
"'&(lt|#60);'i",
"'&(gt|#62);'i",
"'&(nbsp|#160);'i",
"'&(iexcl|#161);'i",
"'&(cent|#162);'i",
"'&(pound|#163);'i",
"'&(copy|#169);'i",
"'&#(\d );'e"); // write as php
$replace = array ("",
"",
"",
"",
"\\1",
"\"",
"&",
"<",
">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
"chr(\\1)");
return preg_replace($search, $replace, $htmlText);
}
(В такие минуты как никогда радует возможность preg_replace работать с массивами в качестве параметров). Массив вы при необходимости дополняете своими регулярками. Помочь в их составлении вам может, например, этот
конструктор регулярных выражений. Начинающим разработчикам может быть полезной статья
"All about HTML tags. 9 Regular Expressions to strip HTML tags". Посмотрите там примеры, проанализируйте логику.
2. От объемов.Объемы напрямую связаны со сложностью анализа (из предыдущего пункта). Большое количество текстов увеличивает вероятность, что, пытаясь предусмотреть и почистить все регулярками, вы можете что-нибудь да упустить. В этом случае подойдет метод "многоступенчатой" очистки. То есть очистить сначала, допустим, функцией strip_tags_smart (исходники на всякий случай не удаляем). Потом выборочно просматриваем некоторое количество текстов на выявление "аномалий". Ну и "зачищаем" аномалии регулярками.
3. От того, что надо получить в результате.Алгоритм обработки может быть упрощен разными способами в зависимости от ситуации. Случай, описанный мной в
одной из предыдущих статей, хорошо это демонстрирует. Напомню, текст там находился в div-е, в котором кроме него был еще div с "хлебными крошками", реклама адсенс, список похожих статей. При анализе выборки статей обнаружилось, что статьи не содержат рисунков и просто разбиты на абзацы с помощью <p></p>. Чтобы не чистить "главный" див от посторонних вещей, можно найти все абзацы (с Simple HTML DOM Parser это очень просто) и соединить их содержимое. Так что прежде чем составлять регулярки для чистки, посмотрите, нельзя ли обойтись малой кровью.
Вообще, между сторонниками парсинга html-кода, основанного чисто на регулярных выражениях, и парсинга, в основе которого лежит анализ DOM-структуры документа, в сети разгораются настоящие холивары. Вот, например, на оверфлоу. Невинный с первого взгляда
вопрос вызвал очень бурное обсуждение (особенно обратите внимание на первый коммент, за который проголосовало уже более 3 тысяч человек, — чувак отжег :) ).
В общем, каждый выбирает то, что ему ближе и что лучше подходит для конкретной ситуации.
А какой способ предпочитаете вы?
___
Чтобы быть в курсе обновлений блога, можно
подписаться на RSS.