web-dev-qa-db-ja.com

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

TinyMCE を使用して、サイト内のテキストの最小限の書式設定を許可します。生成されたHTMLから、電子メール用にプレーンテキストに変換したいと思います。 html2text と呼ばれるクラスを使用してきましたが、特にUTF-8サポートが不足しています。ただし、特定のHTMLタグをプレーンテキスト形式にマップするようにします。以前はHTMLに<i>タグがあったテキストをアンダースコアで囲むようにします。

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

76
Justin Stayton

html2text (例 HTML to text )を使用します。これは Eclipse Public License でライセンスされています。 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のリンク (属性)は、ほとんどのオープンソースライセンスと互換性がありません。
94
jevon

ここに別の解決策があります:

$cleaner_input = strip_tags($text);

消毒機能の他のバリエーションについては、以下を参照してください。

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

16
T.Todua

DOMDocument を使用してHTMLからテキストに変換することは実行可能なソリューションです。 PHP5を必要とするHTML2Textを検討してください。

UTF-8については、「howto」ページに次のように記載されています。

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

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

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

13
lkessler

信頼できる 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)));

?>
11
pestilence669

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
nad2000

この機能をテストできます

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

適切な既存のソリューションが見つかりませんでした-単純な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
5
Rob Quist

convert 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;のようなものを変換します。

4
Jay

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

2
outis

私はOPと同じ問題に遭遇し、上記のトップの回答からいくつかの解決策を試しても、私のシナリオではうまくいかないことがわかりました。最後に理由をご覧ください。

代わりに、混乱を避けるために、この便利なスクリプトを見つけました。GPLで利用可能なhtml2text_roundcubeと呼びましょう。

実際には、既に述べたスクリプトの更新バージョン-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
Chris Dev
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);

出力
string 1
string 2
string 3
string 4
string 5

1
Aommy Indy

Markdownifyは私にとって素晴らしい仕事でした!それについて言及しなければならないこと:それは完全にutf-8をサポートしています。これは、html2text(このスレッドで以前に言及したもの)以外の別のソリューションを探していた主な理由でした。

1
jebbie

私の場合、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?
0
sudip

タグを完全に取り除き、コンテンツをタグ内に保持したくない場合は、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つは、外部パッケージを必要としないことです。

0
supersan