Chuyển đổi HTML sang văn bản thuần trong PHP cho e-mail


80

Tôi sử dụng TinyMCE để cho phép định dạng văn bản tối thiểu trong trang web của mình. Từ HTML được tạo ra, tôi muốn chuyển nó thành văn bản thuần túy cho e-mail. Tôi đang sử dụng một lớp có tên html2text , nhưng nó thực sự thiếu hỗ trợ UTF-8, trong số những thứ khác. Tuy nhiên, tôi làm như vậy, nó ánh xạ một số thẻ HTML nhất định sang định dạng văn bản thuần túy - như đặt dấu gạch dưới xung quanh văn bản mà trước đó có thẻ <i> trong HTML.

Có ai sử dụng phương pháp tương tự để chuyển đổi HTML sang văn bản thuần túy trong PHP không? Và nếu có: Bạn có đề xuất bất kỳ lớp học của bên thứ ba nào mà tôi có thể sử dụng không? Hoặc làm thế nào để bạn giải quyết vấn đề này tốt nhất?




Để tham khảo, wikipedia liên kết đến một cuộc khảo sát cho biết chỉ có khoảng 3% người sử dụng email dạng văn bản.
Redzarf

7
@Redzarf nó không phải về 3% này. Thêm một phần văn bản thuần túy là một ý tưởng thực sự hay nếu bạn không muốn email của mình đi thẳng vào thư mục spam. Thêm vào đó, 3% này có lẽ không tính đến các khách hàng di động nhẹ. Cuối cùng nhưng không kém phần quan trọng: 3% lớn hơn 0%, điều này sẽ khiến bạn phải cân nhắc nghiêm túc.
Ninj

@Ninj Tôi vừa kiểm tra và cuộc khảo sát là từ năm 2002, vì vậy mọi thứ sẽ thay đổi kể từ đó (mặc dù tôi vẫn nghĩ rằng 3% có lẽ là đúng.) Điểm tốt về vấn đề spam - đối với bất kỳ ai đọc bài này sau, những người lo ngại về spam, tôi thấy rằng công cụ này là tuyệt vời: port25.com/support/authentication-center/email-verification
Redzarf

Câu trả lời:


99

Sử dụng html2text (ví dụ HTML thành văn bản ), được cấp phép theo Giấy phép Công cộng Eclipse . Nó sử dụng các phương thức DOM của PHP để tải từ HTML, sau đó lặp qua DOM kết quả để trích xuất văn bản thuần túy. Sử dụng:

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

Mặc dù không đầy đủ, nó là mã nguồn mở và những đóng góp được hoan nghênh.

Vấn đề với các tập lệnh chuyển đổi khác:


1
Tập lệnh đầu tiên ở trên được phát hành theo GPL, không phải là giấy phép "phi thương mại". Tùy thuộc vào ngữ cảnh nó có thể không mong muốn, nhưng nó không phải là "phi thương mại". Liên kết thứ hai cũng cho phép sử dụng thương mại - chỉ với ghi công. Đó cũng không phải là "phi thương mại".
Oliver Moran

1
@OliverMoran Bạn nói đúng, tôi đã chỉnh sửa câu trả lời để phản ánh chính xác hơn các giới hạn giấy phép của họ.
jevon

Cảm ơn bạn @jevon, tôi đã đưa công việc của bạn vào dự án của mình và nó hoạt động rất tốt! Thật không may, nó không giúp giải quyết vấn đề Outlook của tôi ( stackoverflow.com/questions/19135443/… ) nhưng tôi nhận được kết quả rõ ràng theo cách đó.
Ninj

Liên kết bị hỏng. Bỏ phiếu từ chối.
Sibidharan

xin vui lòng làm rõ, nhưng ai sẽ phát hiện nếu ai đó đang sử dụng hoặc không theo GLP hoặc bất cứ điều gì?
Miguel

20

đây là một giải pháp khác:

$cleaner_input = strip_tags($text);

Để biết các biến thể khác của chức năng khử trùng, hãy xem:

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


12
Phiên bản tốt hơn$ClearText = preg_replace( "/\n\s+/", "\n", rtrim(html_entity_decode(strip_tags($HTMLText))) );
mAsT3RpEE

1
điều này rất đơn giản và không cần thư viện khác. cũng hoạt động rất tốt .......... :)
mili

14

Chuyển đổi từ HTML sang văn bản bằng DOMDocument là một giải pháp khả thi. Hãy xem xét HTML2Text, yêu cầu PHP5:

Về UTF-8, phần viết trên trang "cách thực hiện" nêu rõ:

Hỗ trợ riêng của PHP cho unicode khá kém và không phải lúc nào nó cũng xử lý utf-8 một cách chính xác. Mặc dù tập lệnh html2text sử dụng các phương thức unicode an toàn (không cần mô-đun mbstring), nhưng nó không thể luôn đối phó với việc xử lý mã hóa của chính PHP. PHP không thực sự hiểu unicode hoặc các mã hóa như utf-8 và sử dụng mã hóa cơ sở của hệ thống, có xu hướng là một trong họ ISO-8859. Do đó, những gì có thể trông giống như một ký tự hợp lệ trong trình soạn thảo văn bản của bạn, ở dạng utf-8 hoặc byte đơn, cũng có thể bị PHP hiểu sai. Vì vậy, mặc dù bạn nghĩ rằng bạn đang cung cấp một ký tự hợp lệ vào html2text, nhưng bạn cũng có thể không.

Tác giả cung cấp một số cách tiếp cận để giải quyết vấn đề này và tuyên bố rằng phiên bản 2 của HTML2Text (sử dụng DOMDocument) có hỗ trợ UTF-8.

Lưu ý các hạn chế cho việc sử dụng thương mại.


Markdownify không còn được duy trì; bản demo trực tuyến đưa ra nhiều cảnh báo và không hoạt động. Phiên bản mới của html2text không hoạt động cho email của tôi. +1 muộn cho lkessler.
malcanso

13

Có hàm dải_tag đáng tin cậy . Nó không đẹp. Nó sẽ chỉ làm vệ sinh. Bạn có thể kết hợp nó với một chuỗi thay thế để có được dấu gạch dưới ưa thích của bạn.


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

?>

Đừng quên rằng thẻ dải cũng loại bỏ các neo!
Alix Axel

9

Bạn có thể sử dụng lynx với các tùy chọn -stdin và -dump để đạt được điều đó:

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

Bạn có thể kiểm tra chức năng này

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

Cám ơn vì cái này. Hoạt động hiệu quả cho mục đích sử dụng của tôi (chuyển đổi HTML cho nguồn cấp RSS) và cung cấp một mẫu đơn giản để thêm hai trường hợp bổ sung (& rsquo; và & mdash;).
Alan M.

6

Tôi không tìm thấy bất kỳ giải pháp hiện có nào phù hợp - email HTML đơn giản với các tệp văn bản thuần túy đơn giản.

Tôi đã mở kho lưu trữ này, hy vọng nó sẽ giúp ích cho ai đó. Nhân tiện, giấy phép MIT :)

https://github.com/RobQuistNL/SimpleHtmlToText

Thí dụ:

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

trả lại:

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


Newlines

Được gắn cờ là chất lượng thấp về độ dài và nội dung. Tôi không biết. Có thể bài đăng nên nói điều gì đó về cách mã của bạn có thể được sử dụng để trả lời vấn đề hoặc có thể đó là một nhận xét. Các câu trả lời phổ biến nhất dường như chỉ ra cách các giải pháp có thể được gọi từ bên trong mã PHP.
Bill Bell,

Tôi xin lỗi vì đã viết thư viện đó. Tôi đã thêm một ví dụ nhỏ cho bạn nếu bạn không muốn nhấp vào liên kết và xem ví dụ ..
Rob

2
Đừng tiếc! :-) Tôi đã viết với tư cách là một người đánh giá SO. Không phải là tôi không muốn nhấp vào liên kết. Đó là câu trả lời SO yêu cầu rằng một trong những làm được coi là không đạt tiêu chuẩn. Tôi không hiểu tại sao mọi người lại bỏ phiếu tình cờ cho câu trả lời của bạn.
Bill Bell

4

Nếu bạn muốn chuyển đổi các ký tự đặc biệt HTML và không chỉ xóa chúng cũng như tách mọi thứ xuống và chuẩn bị cho văn bản thuần túy thì đây là giải pháp phù hợp với tôi ...

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 chuyển đổi những thứ như &#39; htmlspecialchars_decode chuyển đổi những thứ như &amp; html_entity_decode chuyển đổi những thứ như '&lt; và dải_tag loại bỏ bất kỳ thẻ HTML nào còn sót lại.


3

Markdownify chuyển đổi HTML thành Markdown, một hệ thống định dạng văn bản thuần túy được sử dụng trên chính trang web này.


Một lựa chọn tốt, ngoại trừ cách nó xử lý các liên kết. Nhưng hãy thử bản demo trực tuyến nếu bạn đang cân nhắc.
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);

đầu ra
chuỗi 1
chuỗi 2
chuỗi 3
chuỗi 4
chuỗi 5


1
không thêm câu trả lời. Vui lòng thêm văn bản tại sao đây là câu trả lời
Himanth

2

Tôi đã gặp vấn đề tương tự như OP và việc thử một số giải pháp từ các câu trả lời hàng đầu ở trên không được chứng minh là phù hợp với các tình huống của tôi. Xem tại sao ở phần cuối.

Thay vào đó, tôi thấy tập lệnh hữu ích này, để tránh nhầm lẫn, chúng ta hãy gọi nó là tập lệnh html2text_roundcube, có sẵn theo GPL:

Nó thực sự là một phiên bản cập nhật của một tập lệnh đã được đề cập - http://www.chuggnutt.com/html2text.php- được cập nhật bởi thư RoundCube.

Sử dụng:

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

Tại sao lại html2text_roundcubetỏ ra tốt hơn những cái khác:

  • Tập lệnh http://www.chuggnutt.com/html2text.phpkhông hoạt động tốt đối với các trường hợp có mã / tên HTML đặc biệt (ví dụ &auml;) hoặc dấu ngoặc kép không được ghép nối (ví dụ <p>25" Monitor</p>).

  • Script https://github.com/soundasleep/html2textkhông có tùy chọn để ẩn hoặc nhóm các liên kết ở cuối văn bản, làm cho một trang HTML thông thường trông đầy các liên kết khi ở định dạng văn bản thuần túy; tùy chỉnh mã để xử lý đặc biệt về cách chuyển đổi được thực hiện không dễ dàng như chỉ cần chỉnh sửa một mảng trong html2text_roundcube.


1

Tôi vừa tìm thấy một hàm PHP "strip_tags ()" và nó đang hoạt động trong trường hợp của tôi.

Tôi đã cố gắng chuyển đổi HTML sau:

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

Sau khi áp dụng hàm strip_tags (), tôi có kết quả sau:

&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 () sẽ không xử lý trường hợp bạn có nhiều phần tử trên một số dòng được html coi là 'nội tuyến' và sẽ hiển thị chúng trên nhiều dòng. Ngoài ra, trường hợp ngược lại - nếu bạn có nhiều phần tử div trên một dòng, nó sẽ tách các thẻ và nối nội dung. Tôi đã chia sẻ kinh nghiệm của tôi ở đây: stackoverflow.com/questions/1930297/...
Nikola Petkanski

1

Đối với văn bản trong utf-8, nó hoạt động với tôi mb_convert_encoding. Để xử lý mọi thứ bất kể lỗi, hãy đảm bảo bạn sử dụng ký tự "@".

Mã cơ bản tôi sử dụng là:

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

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

Nếu bạn muốn thứ gì đó nâng cao hơn, bạn có thể phân tích lặp đi lặp lại các nút, nhưng bạn sẽ gặp nhiều vấn đề với khoảng trắng.

Tôi đã triển khai một trình chuyển đổi dựa trên những gì tôi nói ở đây. Nếu bạn quan tâm, bạn có thể tải xuống từ git https://github.com/kranemora/html2text

Nó có thể dùng như một tài liệu tham khảo để làm cho bạn

Bạn có thể sử dụng nó như thế này:

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

0

Nếu bạn không muốn tách các thẻ hoàn toàn và giữ nội dung bên trong các thẻ, bạn có thể sử dụng DOMDocumentvà trích xuất textContentnút gốc như sau:

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!

Một ưu điểm của phương pháp này là nó không yêu cầu bất kỳ gói bên ngoài nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.