Перетворення HTML у звичайний текст у PHP для електронної пошти


80

Я використовую TinyMCE, щоб дозволити мінімальне форматування тексту на моєму сайті. Із створеного HTML-файлу я хотів би перетворити його на звичайний текст для електронної пошти. Я використовував клас під назвою html2text , але йому, серед іншого, не вистачає підтримки UTF-8. Мені, однак, подобається, що він відображає певні теги HTML у форматування простого тексту - як накреслення підкреслення навколо тексту, який раніше мітив теги <i> в HTML.

Хтось використовує подібний підхід для перетворення HTML у звичайний текст у PHP? І якщо так: Чи рекомендуєте Ви якісь сторонні класи, якими я можу користуватися? Або як найкраще вирішити цю проблему?




Для довідки Вікіпедія посилається на опитування, згідно з яким лише близько 3% людей користуються електронною поштою лише з текстом.
Redzarf

8
@Redzarf справа не в цих 3%. Додавання простого тексту - це дійсно хороша ідея, якщо ви не хочете, щоб електронна пошта надходила безпосередньо до папки зі спамом. Крім того, ці 3%, ймовірно, не беруть до уваги легких мобільних клієнтів. І останнє, але не менш важливе: 3% перевищує 0%, що повинно змусити вас розглянути це серйозно.
Ніндж

@Ninj Я щойно перевірив, і опитування було з 2002 року, тому з того часу все зміниться (хоча я все ще вважаю, що 3% - це, мабуть, правильно.) Хороша думка щодо проблеми зі спамом - для тих, хто читає це пізніше, хто стурбований спамом, Я виявив, що цей інструмент був чудовим: port25.com/support/authentication-center/email-verification
Redzarf

Відповіді:


99

Використовуйте 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 несумісне з більшістю ліцензій з відкритим кодом.

1
Перший сценарій вище випущений під GPL, який не є "некомерційною" ліцензією. Залежно від контексту це може бути небажаним, але воно не є "некомерційним". Друге посилання також дозволяє комерційне використання - лише з атрибуцією. Це теж не "некомерційне".
Олівер Моран,

1
@OliverMoran Ви маєте рацію, я відредагував відповідь, щоб точніше відображати обмеження їх ліцензії.
jevon

Дякую @jevon, я включив вашу роботу до свого проекту, і вона чудово працює! На жаль, це не допомогло вирішити мою проблему Outlook ( stackoverflow.com/questions/19135443/… ), але я отримую чистий результат таким чином.
Ніндж

Посилання порушено. Голосування вниз.
Сібідгаран

уточнюйте, будь ласка, але хто виявить, чи хтось використовує GLP чи ні?
Мігель

21

ось ще одне рішення:

$cleaner_input = strip_tags($text);

Інші варіанти функцій санітарної обробки див .:

https://github.com/ttodua/useful-php-scripts/blob/master/filter-php-variable-sanitize.php


13
Краща версія$ClearText = preg_replace( "/\n\s+/", "\n", rtrim(html_entity_decode(strip_tags($HTMLText))) );
mAsT3RpEE

1
це так просто, і не потрібна інша бібліотека. також працює дуже добре .......... :)
мілі

14

Перетворення з HTML на текст за допомогою DOMDocument є життєздатним рішенням. Розглянемо HTML2Text, який вимагає PHP5:

Щодо UTF-8, запис на сторінці "Howto" говорить:

Власна підтримка Unicode PHP досить погана, і вона не завжди правильно обробляє utf-8. Хоча сценарій html2text використовує безпечні для юнікоду методи (без необхідності модуля mbstring), він не завжди може впоратися з власною обробкою кодувань PHP. PHP насправді не розуміє Юнікод або кодування, як utf-8, і використовує базове кодування системи, яка, як правило, належить до сімейства ISO-8859. Як результат, те, що може здатися вам дійсним символом у вашому текстовому редакторі, як у utf-8, так і в однобайтовому, цілком може бути неправильно інтерпретоване PHP. Отже, навіть якщо ви думаєте, що вводите дійсний символ у html2text, ви цілком можете не бути.

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

Зверніть увагу на обмеження для комерційного використання.


Markdownify більше не підтримується; онлайн-демонстрація видає багато попереджень і не працює. Нова версія html2text працює на мою електронну пошту. Пізній +1 до lkessler.
malcanso

13

Є надійна функція 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)));

?>

Не забувайте, що стрічкові мітки також видаляють якорі!
Alix Axel

9

Ви можете використовувати 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";
}

8

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

function html2text($Document) {
    $Rules = array ('@<script[^>]*?>.*?</script>@si',
                    '@<[\/\!]*?[^<>]*?>@si',
                    '@([\r\n])[\s]+@',
                    '@&(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);
}

Дякую за це. Відмінно працював для мого використання (перетворення HTML-коду для RSS-каналу) та містив простий шаблон для додавання двох додаткових випадків (& rsquo; та & mdash;).
Алан М.

6

Я не знайшов жодного з існуючих рішень, що підходить - прості електронні листи 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

Позначено як неякісний за довжиною та змістом. Я не знаю. Можливо, у дописі слід сказати щось про те, як за допомогою вашого коду можна відповісти на проблему, а може, це має бути коментар. Найпопулярніші відповіді показують, як можна викликати рішення з коду PHP.
Білл Белл

Мені шкода, що я написав цю бібліотеку. Я додав для вас невеликий приклад, якщо ви не хочете клацнути на посилання і подивитися на приклад ..
Роб

2
Не шкодуй! :-) Я писав як рецензент. Це не те, що я не хотів натискати посилання. Це те, що відповіді SO вимагають того, щоб зробити те, що вважається неякісним. Не знаю, чому б хтось випадково відмовився від вашої відповіді?
Білл Белл

4

Якщо ви хочете перетворити спеціальні символи 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, перетворює речі, такі як strip_tags '&lt; видаляє будь-які теги HTML, що залишилися.


3

Markdownify перетворює HTML у Markdown, систему форматування в простому тексті, що використовується саме на цьому сайті.


Хороший вибір, за винятком того, як він обробляє посилання. Але спробуйте онлайн-демонстрацію, якщо ви її розглядаєте.
Redzarf

3
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


1
не додавати просто відповідь. Будь ласка, додайте текст, чому це відповідь
Himanth

2

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

Натомість я знайшов цей корисний скрипт, щоб уникнути плутанини, назвемо його html2text_roundcube, доступний під GPL:

Це фактично оновлена ​​версія вже згаданого сценарію - 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виявилося кращим за інших:

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

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


1

Я щойно знайшов 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's 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?

3
strip_tags () не справляється з випадком, коли у вас є кілька елементів у декількох рядках, які HTML розглядає як "вбудовані", і відображатиме їх у декількох рядках. Крім того, зворотний випадок - якщо у вас є кілька елементів div в одному рядку, він видалить теги та об'єднає вміст. Я поділився своїм досвідом тут: stackoverflow.com/questions/1930297 / ...
Нікола Petkanski

1

Якщо ви не хочете повністю видаляти теги та зберігати вміст усередині тегів, ви можете скористатися 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!

Однією з переваг цього підходу є те, що він не вимагає жодних зовнішніх пакетів.


1

Для текстів в 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's <em>works</em> for you?</p>
EOF;

$html2Text = new \kranemora\Html2Text\Html2Text;
$text = $html2Text->convert($html);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.