Skip to content

使用 league/html-to-markdown 在 PHP 中将 HTML 转换为 Markdown

简介

将 HTML 转换为 Markdown 是处理网页抓取、CMS 迁移、RSS 订阅处理或为 LLM 准备内容时的常见需求。league/html-to-markdown 库提供了一个经过实战检验的强大解决方案,下载量超过 2400 万次。

本文涵盖安装、配置选项、表格支持以及处理不受信任输入时的安全注意事项。

安装

通过 Composer 安装:

bash
composer require league/html-to-markdown

该库需要 PHP 7.2+ 以及 xmllibxmldom 扩展(大多数发行版默认启用)。

基本用法

php
use League\HTMLToMarkdown\HtmlConverter;

$converter = new HtmlConverter();

$html = '<h1>你好世界</h1><p>这是一个<strong>测试</strong>。</p>';
$markdown = $converter->convert($html);

echo $markdown;
// # 你好世界
//
// 这是一个**测试**。

配置选项

转换器接受一个选项数组:

php
$converter = new HtmlConverter([
    'strip_tags' => true,
    'remove_nodes' => 'script style',
    'hard_break' => true,
    'strip_placeholder_links' => true,
]);

主要选项说明

选项默认值描述
strip_tagsfalse移除没有 Markdown 等效项的 HTML 标签,保留其内容
remove_nodes''用空格分隔的标签列表,完全移除(包括内容)
hard_breakfalse<br> 转换为 \n 而不是 \n(GFM 风格)
strip_placeholder_linksfalse移除没有 href 属性的 <a> 标签
header_style'setext'使用 'atx' 为 H1/H2 使用 # 风格标题
preserve_commentsfalse在输出中保留 HTML 注释

网页抓取的推荐配置

转换抓取的 HTML 时,通常需要移除导航、脚本和其他非内容元素:

php
$converter = new HtmlConverter([
    'strip_tags' => true,
    'remove_nodes' => 'script head style noscript nav footer aside header',
    'hard_break' => true,
    'strip_placeholder_links' => true,
]);

添加表格支持

表格转换默认未启用,因为表格不是原始 Markdown 规范的一部分。使用 TableConverter 添加支持:

php
use League\HTMLToMarkdown\HtmlConverter;
use League\HTMLToMarkdown\Converter\TableConverter;

$converter = new HtmlConverter(['strip_tags' => true]);
$converter->getEnvironment()->addConverter(new TableConverter());

$html = '
<table>
    <tr><th>姓名</th><th>角色</th></tr>
    <tr><td>Alice</td><td>开发者</td></tr>
    <tr><td>Bob</td><td>设计师</td></tr>
</table>';

echo $converter->convert($html);
// | 姓名 | 角色 |
// | --- | --- |
// | Alice | 开发者 |
// | Bob | 设计师 |

实际示例:网页抓取管道

这是一个将抓取的 HTML 转换为干净 Markdown 的完整实用函数:

php
use League\HTMLToMarkdown\Converter\TableConverter;
use League\HTMLToMarkdown\HtmlConverter;

function htmlToMarkdown(string $html): string
{
    $converter = new HtmlConverter([
        'strip_tags' => true,
        'remove_nodes' => 'script head style noscript nav footer aside header',
        'hard_break' => true,
        'strip_placeholder_links' => true,
    ]);

    $converter->getEnvironment()->addConverter(new TableConverter());

    return $converter->convert($html);
}

// 用法
$html = file_get_contents('https://example.com/article');
$markdown = htmlToMarkdown($html);

预处理:清理语法高亮代码

抓取文档网站时,代码块通常包含用于语法高亮的 <span> 标签。这会使 Markdown 输出变得混乱。在转换前进行清理:

php
function removeSpansFromCode(string $html): string
{
    $dom = new DOMDocument('1.0', 'UTF-8');

    libxml_use_internal_errors(true);
    $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    libxml_clear_errors();

    $xpath = new DOMXPath($dom);
    $spans = $xpath->query('//pre//span | //code//span');

    foreach ($spans as $span) {
        while ($span->childNodes->length > 0) {
            $span->parentNode->insertBefore($span->childNodes->item(0), $span);
        }
        $span->parentNode->removeChild($span);
    }

    return trim($dom->saveHTML());
}

// 用法:转换前清理 HTML
$cleanHtml = removeSpansFromCode($html);
$markdown = htmlToMarkdown($cleanHtml);

安全注意事项

重要

默认情况下,该库会保留未识别的标签,如 <script><iframe><div>。处理不受信任的用户输入时,务必启用 strip_tagsremove_nodes

对于用户生成的内容,结合 HTML Purifier 以增加安全性:

php
use HTMLPurifier;
use HTMLPurifier_Config;
use League\HTMLToMarkdown\HtmlConverter;

function safeHtmlToMarkdown(string $untrustedHtml): string
{
    // 首先,使用 HTML Purifier 清理
    $config = HTMLPurifier_Config::createDefault();
    $purifier = new HTMLPurifier($config);
    $cleanHtml = $purifier->purify($untrustedHtml);

    // 然后转换为 Markdown
    $converter = new HtmlConverter([
        'strip_tags' => true,
        'remove_nodes' => 'script style iframe object embed',
    ]);

    return $converter->convert($cleanHtml);
}

常见问题

找不到 DOMDocument

在 CentOS 或最小化 PHP 安装中,你可能会看到:

Fatal error: Class 'DOMDocument' not found

通过安装 PHP XML 扩展来修复:

bash
# CentOS/RHEL
sudo yum install php-xml

# Ubuntu/Debian
sudo apt-get install php-xml

HTML 格式错误警告

抑制格式错误 HTML 的警告(抓取内容常见):

php
$converter = new HtmlConverter(['suppress_errors' => true]);

总结

league/html-to-markdown 库以合理的默认值和广泛的自定义选项处理 HTML 到 Markdown 转换的复杂性。要点:

  • 使用 strip_tagsremove_nodes 清理不需要的元素
  • 添加 TableConverter 以支持表格
  • 处理前务必清理不受信任的输入
  • 预处理语法高亮代码块以获得更干净的输出

对于 LLM 管道或内容处理,这种配置选项组合可以从几乎任何 HTML 源获得干净、可读的 Markdown。