web-dev-qa-db-fra.com

Conversion de HTML en texte brut dans PHP pour le courrier électronique

J'utilise TinyMCE pour permettre une mise en forme minimale du texte sur mon site. À partir du code HTML produit, j'aimerais le convertir en texte brut pour le courrier électronique. J'utilise une classe appelée html2text , mais le support UTF-8, entre autres, manque vraiment. Cependant, comme cela, je mappe certaines balises HTML au format de texte brut, comme si vous mettiez des soulignements autour du texte qui comportait auparavant des balises <i> dans le code HTML.

Est-ce que quelqu'un utilise une approche similaire pour convertir HTML en texte brut en PHP? Et si oui: Recommandez-vous des cours tiers que je peux utiliser? Ou comment vous attaquer au mieux à ce problème?

71
Justin Stayton

Utilisez html2text (exemple HTML à text ), sous licence Eclipse Public License . Il utilise les méthodes DOM de PHP pour charger du HTML, puis itère sur le DOM résultant pour extraire le texte brut. Usage:

// 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);

Bien que incomplet, il est open source et les contributions sont les bienvenues.

Problèmes avec d'autres scripts de conversion:

  • Étant donné que html2text (GPL) n'est pas compatible avec EPL.
  • Le lien de lkessler (attribution) est incompatible avec la plupart des licences open source.
89
jevon

Il y a la confiance strip_tags fonction. Ce n'est pas joli quand même. Ça ne fera que désinfecter. Vous pouvez le combiner avec une chaîne de remplacement pour obtenir votre soulignement de fantaisie.


<?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)));

?>
12
pestilence669

La conversion de HTML en texte à l'aide de DOMDocument est une solution viable. Considérons HTML2Text, qui nécessite PHP5:

En ce qui concerne UTF-8, la rédaction de la page "howto" indique:

La propre prise en charge de PHP par Unicode est assez médiocre et ne gère pas toujours correctement utf-8. Bien que le script html2text utilise des méthodes sûres pour l'unicode (sans avoir besoin du module mbstring), il ne peut pas toujours gérer le traitement des codages par PHP. PHP ne comprend pas vraiment le codage Unicode ou les codages comme utf-8, et utilise le codage de base du système, qui est généralement de la famille ISO-8859. En conséquence, ce qui peut vous sembler être un caractère valide dans votre éditeur de texte, qu’il soit utf-8 ou mono-octet, pourrait bien être mal interprété par PHP. Ainsi, même si vous pensez introduire un caractère valide dans html2text, il se peut que vous ne le soyez pas.

L'auteur propose plusieurs approches pour résoudre ce problème et indique que la version 2 de HTML2Text (utilisant DOMDocument) prend en charge UTF-8.

Notez les restrictions pour une utilisation commerciale.

12
lkessler

voici une autre solution:

$cleaner_input = strip_tags($text);

Pour d'autres variantes des fonctions de désinfection, voir:

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

11
T.Todua

Vous pouvez utiliser lynx avec les options -stdin et -dump pour y parvenir:

<?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
nad2000

Vous pouvez tester cette fonction

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);
}
7
HoangLong85

Je n'ai trouvé aucune des solutions existantes qui conviennent - des courriers électroniques HTML simples à des fichiers texte simples.

J'ai ouvert ce référentiel, j'espère que cela aidera quelqu'un. Licence MIT, au fait :)

https://github.com/RobQuistNL/SimpleHtmlToText

Exemple:

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

résultats:

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


Newlines
5
Rob Quist

Si vous voulez convertir les caractères spéciaux HTML et non pas simplement les supprimer, mais aussi les dépouiller et préparer le texte brut, cette solution a fonctionné pour moi ...

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 avec ENT_QUOTES | ENT_XML1 convertit des éléments tels que &#39; Htmlspecialchars_decode convertit des éléments tels que &amp; Html_entity_decode convertit des éléments tels que '&lt; Et strip_tags supprime les balises HTML restantes.

2
Jay

Markdownify convertit le HTML en Markdown, un système de formatage de texte en clair utilisé sur ce site même.

2
outis

Je suis venu sur le même problème que le PO, et essayer quelques solutions parmi les réponses ci-dessus n'a pas fonctionné pour mes scénarios. Voyez pourquoi à la fin.

Au lieu de cela, j'ai trouvé ce script utile, pour éviter toute confusion, appelons-le html2text_roundcube, disponible sous GPL:

C'est en fait une version mise à jour d'un script déjà mentionné - http://www.chuggnutt.com/html2text.php - mis à jour par mail RoundCube.

Usage:

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

Pourquoi html2text_roundcube s'est avéré meilleur que les autres:

  • Le script http://www.chuggnutt.com/html2text.php ne fonctionnait pas avec les cas avec des codes/noms HTML spéciaux (par exemple, &auml;) ou des guillemets non associés (par exemple, <p>25" Monitor</p>).

  • Script https://github.com/soundasleep/html2text n'avait pas la possibilité de masquer ou de regrouper les liens à la fin du texte, ce qui donnait l'impression qu'une page HTML ordinaire était surchargée de liens au format texte brut; La personnalisation du code pour un traitement spécial de la manière dont la transformation est effectuée n'est pas aussi simple que de simplement éditer un tableau dans html2text_roundcube.

1
Chris Dev

Markdownify a fonctionné à merveille pour moi! ce qui doit être mentionné à ce sujet: il supporte parfaitement utf-8, quelle était la raison principale pour laquelle je cherchais une autre solution que html2text (ce qui a été mentionné précédemment dans ce fil).

1
jebbie

Je viens de trouver une fonction PHP "strip_tags ()" et cela fonctionne dans mon cas.

J'ai essayé de convertir le code HTML suivant:

<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>

Après avoir appliqué la fonction strip_tags (), j'ai la sortie suivante:

&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?
0
sudip

Si vous ne souhaitez pas supprimer complètement les balises et conserver le contenu à l'intérieur, vous pouvez utiliser la variable DOMDocument et extraire la variable textContent du nœud racine comme suit:

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!

L'un des avantages de cette approche est qu'elle ne nécessite aucun package externe.

0
supersan