Преобразование HTML в обычный текст в PHP для электронной почты

Я использую TinyMCE, чтобы разрешить минимальное форматирование текста на моем сайте. Из созданного HTML я хотел бы преобразовать его в обычный текст для электронной почты. Я использую класс под названием html2text, но он действительно не поддерживает поддержку UTF-8, среди прочего. Тем не менее, я делаю так, что он сопоставляет определенные теги HTML с форматированием обычного текста - например, помещает подчеркивания вокруг текста, который ранее имел < я > теги в HTML.

Кто-нибудь использует аналогичный подход для преобразования HTML в обычный текст в PHP? И если да: рекомендуете ли вы какие-либо сторонние классы, которые я могу использовать? Или как вам лучше всего решить эту проблему?

Ответ 1

Используйте html2text (пример HTML - текст), лицензированный по Общественной лицензии Eclipse. Он использует методы PHP DOM для загрузки из HTML, а затем перебирает полученный DOM для извлечения простого текста. Использование:

// when installed using the Composer package
$text = Html2Text\Html2Text::convert($html);

// usage when installed using html2text.php
require('html2text.php');
$text = convert_html_to_text($html);

Несмотря на то, что он неполный, он с открытым исходным кодом и приветствуется.

Проблемы с другими сценариями преобразования:

  • Поскольку html2text (GPL) не совместим с EPL.
  • Ссылка lkessler (атрибуция) несовместима с большинством лицензий с открытым исходным кодом.

Ответ 3

Преобразование из HTML в текст с помощью DOMDocument является жизнеспособным решением. Рассмотрим HTML2Text, для которого требуется PHP5:

Что касается UTF-8, запись на странице "howto" гласит:

Собственная поддержка PHP для юникода довольно бедна, и она не всегда корректно обрабатывает utf-8. Хотя html2text script использует unicode-safe методы (без использования модуля mbstring), он не всегда может справиться с PHP собственной обработкой кодировок. PHP действительно не понимает юникод или кодировки, такие как utf-8, и использует базовую кодировку системы, которая, как правило, является одним из семейств ISO-8859. В результате, то, что может выглядеть вам как действительный символ в вашем текстовом редакторе, как в utf-8, так и в однобайтном, вполне может быть неверно истолковано PHP. Так что, даже если вы думаете, что вы кормите действительного символа в html2text, вы, возможно, не будете.

Автор предлагает несколько подходов к решению этого вопроса и утверждает, что версия 2 HTML2Text (с использованием DOMDocument) поддерживает UTF-8.

Обратите внимание на ограничения для коммерческого использования.

Ответ 4

Здесь есть надежная функция strip_tags. Это не очень. Это будет только санировать. Вы можете комбинировать его с заменой строки, чтобы получить свои необычные подчеркивания.


<?php
// to strip all tags and wrap italics with underscore
strip_tags(str_replace(array("<i>", "</i>"), array("_", "_"), $text));

// to preserve anchors...
str_replace("|a", "<a", strip_tags(str_replace("<a", "|a", $text)));

?>

Ответ 5

Вы можете использовать lynx с параметрами -stdin и -dump, чтобы достичь этого:

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("file", "/tmp/htmp2txt.log", "a") // stderr is a file to write to
);

$process = proc_open('lynx -stdin -dump 2>&1', $descriptorspec, $pipes, '/tmp', NULL);

if (is_resource($process)) {
    // $pipes now looks like this:
    // 0 => writeable handle connected to child stdin
    // 1 => readable handle connected to child stdout
    // Any error output will be appended to htmp2txt.log

    $stdin = $pipes[0];
    fwrite($stdin,  <<<'EOT'
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
 <title>TEST</title>
</head>
<body>
<h1><span>Lorem Ipsum</span></h1>

<h4>"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."</h4>
<h5>"There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain..."</h5>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque et sapien ut erat porttitor suscipit id nec dui. Nam rhoncus mauris ac dui tristique bibendum. Aliquam molestie placerat gravida. Duis vitae tortor gravida libero semper cursus eu ut tortor. Nunc id orci orci. Suspendisse potenti. Phasellus vehicula leo sed erat rutrum sed blandit purus convallis.
</p>
<p>
Aliquam feugiat, neque a tempus rhoncus, neque dolor vulputate eros, non pellentesque elit lacus ut nunc. Pellentesque vel purus libero, ultrices condimentum lorem. Nam dictum faucibus mollis. Praesent adipiscing nunc sed dui ultricies molestie. Quisque facilisis purus quis felis molestie ut accumsan felis ultricies. Curabitur euismod est id est pretium accumsan. Praesent a mi in dolor feugiat vehicula quis at elit. Mauris lacus mauris, laoreet non molestie nec, adipiscing a nulla. Nullam rutrum, libero id pellentesque tempus, erat nibh ornare dolor, id accumsan est risus at leo. In convallis felis at eros condimentum adipiscing aliquam nisi faucibus. Integer arcu ligula, porttitor in fermentum vitae, lacinia nec dui.
</p>
</body>
</html>
EOT
    );
    fclose($stdin);

    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    // It is important that you close any pipes before calling
    // proc_close in order to avoid a deadlock
    $return_value = proc_close($process);

    echo "command returned $return_value\n";
}

Ответ 6

Вы можете проверить эту функцию

function html2text($Document) {
    $Rules = array ('@<script[^>]*?>.*?</script>@si',
                    '@<[\/\!]*?[^<>]*?>@si',
                    '@([\r\n])[\s][email protected]',
                    '@&(quot|#34);@i',
                    '@&(amp|#38);@i',
                    '@&(lt|#60);@i',
                    '@&(gt|#62);@i',
                    '@&(nbsp|#160);@i',
                    '@&(iexcl|#161);@i',
                    '@&(cent|#162);@i',
                    '@&(pound|#163);@i',
                    '@&(copy|#169);@i',
                    '@&(reg|#174);@i',
                    '@&#(d+);@e'
             );
    $Replace = array ('',
                      '',
                      '',
                      '',
                      '&',
                      '<',
                      '>',
                      ' ',
                      chr(161),
                      chr(162),
                      chr(163),
                      chr(169),
                      chr(174),
                      'chr()'
                );
  return preg_replace($Rules, $Replace, $Document);
}

Ответ 7

Я не нашел ни одного из существующих решений, подходящих - простые электронные письма HTML к простым текстовым файлам.

Я открыл этот репозиторий, надеюсь, он кому-нибудь поможет. Кстати, лицензия MIT :)

https://github.com/RobQuistNL/SimpleHtmlToText

Пример:

$myHtml = '<b>This is HTML</b><h1>Header</h1><br/><br/>Newlines';
echo (new Parser())->parseString($myHtml);

возвращений:

**This is HTML**
### Header ###


Newlines

Ответ 8

Если вы хотите преобразовать специальные символы HTML, а не просто удалить их, а также вырезать их и подготовить к простому тексту, это решение подойдет мне...

function htmlToPlainText($str){
    $str = str_replace('&nbsp;', ' ', $str);
    $str = html_entity_decode($str, ENT_QUOTES | ENT_COMPAT , 'UTF-8');
    $str = html_entity_decode($str, ENT_HTML5, 'UTF-8');
    $str = html_entity_decode($str);
    $str = htmlspecialchars_decode($str);
    $str = strip_tags($str);

    return $str;
}

$string = '<p>this is (&nbsp;) a test</p>
<div>Yes this is! &amp; does it get "processed"? </div>'

htmlToPlainText($string);
// "this is ( ) a test. Yes this is! & does it get processed?"'

html_entity_decode w/ENT_QUOTES | ENT_XML1 преобразует такие вещи, как &#39; htmlspecialchars_decode преобразует такие вещи, как &amp; html_entity_decode преобразует такие вещи, как '&lt; и strip_tags удаляет все оставшиеся HTML-теги.

Ответ 9

Markdownify преобразует HTML в Markdown, систему форматирования с открытым текстом, используемую на этом самом сайте.

Ответ 10

Markdownify работал замечательно для меня! о чем нужно упомянуть: он отлично поддерживает utf-8, что было основной причиной, по которой я искал другое решение, чем html2text (что упоминалось ранее в этом потоке).

Ответ 11

Я столкнулся с той же проблемой, что и OP, и попробовал некоторые решения из верхних ответов выше, не работал для моих сценариев. Посмотрите, почему в конце.

Вместо этого я нашел этот полезный script, чтобы избежать путаницы, позвоните ему html2text_roundcube, доступный под GPL:

На самом деле это обновленная версия уже упомянутого script - http://www.chuggnutt.com/html2text.php - обновлена ​​по почте RoundCube.

Использование:

$h2t = new \Html2Text\Html2Text('Hello, &quot;<b>world</b>&quot;');
echo $h2t->getText(); // prints Hello, "WORLD"

Почему html2text_roundcube оказался лучше других:

  • Script http://www.chuggnutt.com/html2text.php не работает из коробки для случаев со специальными кодами/именами HTML (например, &auml;) или неспаренными кавычками (например, <p>25" Monitor</p>).

  • Script https://github.com/soundasleep/html2text не имел возможности скрывать или группировать ссылки в конце текста, делая обычную HTML-страницу выглядящей раздутой со ссылками в текстовом формате; настройка кода для специальной обработки того, как делается преобразование, не так прямо, как простое редактирование массива в html2text_roundcube.

Ответ 12

public function plainText($text)
{
    $text = strip_tags($text, '<br><p><li>');
    $text = preg_replace ('/<[^>]*>/', PHP_EOL, $text);

    return $text;
}

$text = "string 1<br>string 2<br/><ul><li>string 3</li><li>string 4</li></ul><p>string 5</p>";

echo planText($text);

выход
строка 1
строка 2
Строка 3
Строка 4
строка 5

Ответ 13

Я только что нашел функцию PHP "strip_tags()" и ее работу в моем случае.

Я попытался преобразовать следующий HTML:

<p><span style="font-family: 'Verdana','sans-serif'; color: black; font-size: 7.5pt;">&nbsp;</span>Many  practitioners are optimistic that the eyeglass and contact lens  industry will recover from the recent economic storm. Did your practice  feel its affects?&nbsp; Statistics show revenue notably declined in 2008 and  2009. But interestingly enough, those that monitor these trends state  that despite the industry lackluster performance during this time,  revenue has grown at an average annual rate&nbsp;of 2.2% over the last five  years, to $9.0 billion in 2010.&nbsp; So despite the downturn, how were we  able to manage growth as an industry?</p>

После применения функции strip_tags() у меня есть следующий вывод:

&amp;nbsp;Many  practitioners are optimistic that the eyeglass and contact lens  industry will recover from the recent economic storm. Did your practice  feel its affects?&amp;nbsp; Statistics show revenue notably declined in 2008 and  2009. But interestingly enough, those that monitor these trends state  that despite the industry&#039;s lackluster performance during this time,  revenue has grown at an average annual rate&amp;nbsp;of 2.2% over the last five  years, to $9.0 billion in 2010.&amp;nbsp; So despite the downturn, how were we  able to manage growth as an industry?

Ответ 14

Если вы не хотите полностью удалять теги и хранить содержимое внутри тегов, вы можете использовать DOMDocument и извлечь textContent корневого узла следующим образом:

function html2text($html) {
    $dom = new DOMDocument();
    $dom->loadHTML("<body>" . strip_tags($html, '<b><a><i><div><span><p>') . "</body>");
    $xpath = new DOMXPath($dom);
    $node = $xpath->query('body')->item(0);
    return $node->textContent; // text
}

$p = 'this is <b>test</b>. <p>how are <i>you?</i>. <a href="#">I\'m fine!</a></p>';
print html2text($p);
// this is test. how are you?. I'm fine!

Одним из преимуществ этого подхода является то, что он не требует никаких внешних пакетов.

Ответ 15

Для текстов в utf-8 у меня это сработало mb_convert_encoding. Чтобы обрабатывать все, независимо от ошибок, обязательно используйте "@".

Основной код, который я использую:

$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));

$body = $dom->getElementsByTagName('body')->item(0);
echo $body->textContent;

Если вы хотите что-то более продвинутое, вы можете итеративно анализировать узлы, но вы столкнетесь со многими проблемами с пробелами.

Я реализовал конвертер на основе того, что я здесь говорю. Если вам интересно, вы можете скачать его с git https://github.com/kranemora/html2text

Это может служить ссылкой, чтобы сделать ваш

Вы можете использовать это так:

$html = <<<EOF
<p>Welcome to <strong>html2text<strong></p>
<p>It <em>works</em> for you?</p>
EOF;

$html2Text = new \kranemora\Html2Text\Html2Text;
$text = $html2Text->convert($html);