電子メール用のPHPでHTMLをプレーンテキストに変換する


80

TinyMCEを使用して、サイト内のテキストのフォーマットを最小限に抑えています。作成したHTMLから、メール用のプレーンテキストに変換したいと思います。私はhtml2textというクラスを使用してきましたが、UTF-8のサポートなどが本当に不足しています。ただし、以前はHTMLに<i>タグが付いていたテキストをアンダースコアで囲むなど、特定のHTMLタグをプレーンテキスト形式にマップするのは好きです。

PHPでHTMLをプレーンテキストに変換するために同様のアプローチを使用している人はいますか?もしそうなら:私が使用できるサードパーティのクラスをお勧めしますか?または、この問題にどのように取り組むのが最善ですか?




参考までに、ウィキペディアは、テキストのみの電子メールを使用しているのは約3%に過ぎないと述べた調査にリンクしています。
Redzarf 2013

8
@Redzarfそれはこれらの3%についてではありません。電子メールをスパムフォルダに直接送信したくない場合は、プレーンテキスト部分を追加することをお勧めします。さらに、これらの3%は、おそらく軽いモバイルクライアントを考慮していません。最後になりましたが、3%は0%よりも大きいため、真剣に検討する必要があります。
ninj 2013年

@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の下でリリースされています。状況によっては望ましくない場合もありますが、「非営利」ではありません。2番目のリンクでは、帰属表示だけで商用利用も可能です。それも「非営利」ではありません。
オリバーモラン

1
@OliverMoranそうです、ライセンスの制限をより正確に反映するように回答を編集しました。
jevon 2013年

@jevonに感謝します、私はあなたの仕事を私のプロジェクトに含めました、そしてそれはうまくいきます!残念ながら、Outlookの問題(stackoverflow.com/questions/19135443/…)を解決するのに役立ちませんでしたが、その方法できれいな結果が得られます。
ninj 2013年

リンクが壊れています。反対票。
シビダラン2016年

明確にしてください、しかし誰かが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 2014年

1
これはとてもシンプルで、別のライブラリは必要ありません。また、非常にうまく機能しています.......... :)
mili 2018年

14

DOMDocumentを使用してHTMLからテキストに変換することは実行可能なソリューションです。PHP5を必要とするHTML2Textについて考えてみましょう。

UTF-8に関して、「ハウツー」ページの記事には次のように記載されています。

PHP独自のUnicodeのサポートは非​​常に貧弱であり、utf-8を常に正しく処理するとは限りません。html2textスクリプトは(mbstringモジュールを必要とせずに)Unicodeで安全な方法を使用しますが、PHP独自のエンコーディング処理に常に対応できるとは限りません。PHPは、Unicodeやutf-8のようなエンコーディングを実際には理解しておらず、ISO-8859ファミリの1つである傾向があるシステムのベースエンコーディングを使用します。その結果、テキストエディタでutf-8またはシングルバイトの有効な文字のように見えるものが、PHPによって誤って解釈される可能性があります。したがって、有効な文字をhtml2textにフィードしていると思っていても、そうではない可能性があります。

著者はこれを解決するためのいくつかのアプローチを提供し、HTML2Textのバージョン2(DOMDocumentを使用)はUTF-8をサポートしていると述べています。

商用利用の制限に注意してください。


Markdownifyは維持されなくなりました。オンラインデモは多くの警告をスローし、機能しません。新しいバージョンのhtml2textは私のメールでも機能します。lkesslerへの遅い+1。
マルカンソ2013

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

これをありがとう。私の使用(RSSフィード用のHTMLの変換)に最適で、2つのケース(&rsquo;と&mdash;)を追加するための簡単なテンプレートを提供しました。
Alan M.

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レビュアーとして書いていました。リンクをクリックしたくなかったわけではありません。それは、標準以下と見なされることを要求する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; 変換し'&lt; ますhtml_entity_decodeのようなものを変換し、strip_tagsは残っているHTMLタグを削除します。


3

Markdownifyは、HTMLをMarkdownに変換します。これは、このサイトで使用されているプレーンテキストのフォーマットシステムです。


リンクの処理方法を除いて、良い選択です。ただし、検討している場合は、オンラインデモを試してください。
Redzarf 2013

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 2017

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によって「インライン」と見なされる複数の行に複数の要素があり、それらを複数の行に表示する場合を処理しません。また、逆の場合-1行に複数の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つは、外部パッケージを必要としないことです。


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;

より高度なものが必要な場合は、ノードを繰り返し分析できますが、空白に関して多くの問題が発生します。

私はここで言うことに基づいてコンバーターを実装しました。興味がある場合は、githttps ://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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.