菜鸟科技网

如何把一篇文章图和文字分离出来 php

PHP 结合正则表达式匹配提取文本,借助图像处理库(如 GD)解析并分离图片,实现图文分离

PHP中实现将一篇文章中的图片与文字分离出来是一个常见需求,尤其适用于内容管理系统、文档处理或数据挖掘场景,以下是详细的技术方案和实现步骤:

如何把一篇文章图和文字分离出来 php-图1
(图片来源网络,侵删)

核心思路解析

要实现图文分离,本质上需要完成两个任务: 1️⃣ 提取所有嵌入的图像URL/路径(包括本地文件和网络资源) 2️⃣ 清理纯文本内容并保留结构化信息 这可以通过组合使用正则表达式匹配、DOM文档解析以及字符串处理函数来实现,下面将分模块详细说明具体实现方法。


✅ 方法一:基于正则表达式的基础方案(适合简单HTML结构)

function extractImagesAndText($htmlContent) {
    // 匹配<img>标签及其属性
    preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]>/i', $htmlContent, $matches);
    $images = $matches[1]; // 获取所有图片地址数组
    // 移除所有<img>标签保留文字部分
    $plainText = preg_replace('/<img[^>]+>/i', '', $htmlContent);
    return [
        'images' => array_unique($images), // 去重处理
        'text' => strip_tags($plainText) // 进一步清除残余HTML标签
    ];
}

⚠️ 局限性说明:此方法仅适用于标准写法的<img>标签,无法处理以下情况:

  • 自闭合标签外的嵌套结构(如带div包裹的图片)
  • Base64编码内联图片(data:image/png;base64...)
  • JavaScript动态加载的图片懒加载场景

🔧 进阶方案:使用DOMDocument对象解析(推荐)

通过加载完整的DOM树结构,可以更精准地定位元素节点:

libxml_use_internal_errors(true); // 抑制XML错误警告
$dom = new DOMDocument();
@$dom->loadHTML($htmlContent); // @符号忽略解析错误
// 收集所有img元素
$imageNodes = $dom->getElementsByTagName('img');
foreach ($imageNodes as $node) {
    $src = $node->getAttribute('src');
    if (!empty($src)) {
        $images[] = htmlspecialchars_decode($src); // 解码实体字符
    }
}
// 创建无图版本的文档片段
$body = $dom->getElementsByTagName('body')->item(0);
$fragment = $dom->createDocumentFragment();
while ($body->firstChild) {
    $child = $body->firstChild;
    if ($child->nodeName == 'img') {
        $body->removeChild($child); // 删除图片节点
    } else {
        $fragment->appendChild($child); // 保留其他内容
    }
}
$dom->appendChild($fragment);
$cleanedHtml = $dom->saveHTML(); // 生成净化后的HTML
$plainText = strip_tags($cleanedHtml);

👉 优势对比:该方法能正确处理复杂嵌套结构,支持相对路径转换,并且可通过XPath进行高级查询(例如//img[contains(@class, 'thumbnail')])。

如何把一篇文章图和文字分离出来 php-图2
(图片来源网络,侵删)

📊 性能优化建议(大文件处理)

当处理超过1MB的大型文档时,建议采用流式处理: | 策略 | 实现方式 | 适用场景 | |---------------------|--------------------------------------------------------------------------|------------------------------| | 分段加载 | 使用file_get_contents()配合fseek()逐块读取 | 超长文章避免内存溢出 | | 延迟解析 | 仅在检测到<img>区域时激活DOM解析器 | 稀疏分布的图片布局 | | 缓存机制 | 对已解析过的节点建立哈希表索引 | 重复出现的相同结构元素 |


🛠️ 特殊场景解决方案

1️⃣ Base64内联图片提取

preg_match_all('/src="data:image\/(\w+);base64,(.?)"/', $htmlContent, $base64Matches);
foreach ($base64Matches[0] as $index => $fullMatch) {
    list(, $mimeType, $encodedData) = explode(';', substr($fullMatch, strpos($fullMatch, 'base64')));
    $binaryData = base64_decode($encodedData);
    // 保存为临时文件示例
    file_put_contents("temp_{$index}.{$mimeType}", $binaryData);
}

2️⃣ CSS背景图捕获:需要额外解析样式表并关联对应元素 3️⃣ SVG矢量图形处理:将其视为独立资源单独存储


📌 完整工作流示例

class ArticleProcessor {
    private $originalHtml;
    private $extractedImages = [];
    private $processedText = '';
    public function __construct($input) {
        $this->originalHtml = $input;
    }
    public function process() {
        // Step 1: 初始化DOM环境
        $this->initDomParser();
        // Step 2: 并行执行图文分离任务
        $this->findAllImages()->removeImageTags();
        // Step 3: 后处理优化
        $this->normalizeWhitespace();
        $this->repairBrokenLinks();
        return [
            'images' => array_values(array_filter($this->extractedImages)),
            'text' => $this->getProcessedContent()
        ];
    }
    private function initDomParser() {
        // ...同前文DOM实现细节...
    }
    private function findAllImages() {
        // 实现细节参照前述DOM方案
    }
    private function removeImageTags() {
        // 使用DOM API安全删除节点而非简单替换
    }
    private function normalizeWhitespace() {
        $this->processedText = preg_replace('/[\r\n]+/', "\n", $this->processedText);
    }
    private function repairBrokenLinks() {
        // 修复因删图导致的段落错位问题
    }
    private function getProcessedContent() {
        return trim(strip_tags($this->dom->saveHTML()));
    }
}

▶️ 调用示例

如何把一篇文章图和文字分离出来 php-图3
(图片来源网络,侵删)
$processor = new ArticleProcessor($articleHtml);
list($images, $text) = $processor->process();
print_r($images); // Array ([0] => 'path/to/image1.jpg', ...)
echo nl2br($text); // 格式化后的纯文本输出

💡 典型应用场景扩展

  • 📚 在线教育平台:自动生成课件大纲时剔除干扰性配图
  • 📱 移动端适配:优先加载文字内容再异步请求图片资源
  • 🔍 SEO优化工具:分析页面主要内容密度与多媒体占比关系
  • 🎨 设计素材库建设:批量归档文章中使用的视觉元素

⚠️ 常见问题排查指南

现象 可能原因 解决方案
漏掉某些图片 CSS背景图未被扫描 添加对style属性的解析逻辑
文本出现乱码 字符编码不一致 确保使用UTF-8编码保存中间结果
相对路径失效 URL未转换为绝对路径 使用basename()+基础目录拼接
内存消耗过大 超大文件一次性加载 改用XMLReader逐节点遍历模式

FAQs(相关问答)

Q1: 如果文章中的图片使用的是绝对路径怎么办?是否需要特殊处理?
A: PHP本身不限制路径类型,但建议统一转换为相对路径以便移植,可通过检测是否以协议开头(如http://)来判断外部资源,本地文件保持相对路径即可,对于混合来源的情况,可以用关联数组分别存储不同类别的资源链接。

Q2: 如何处理表格内的嵌套图片?比如某个单元格里既有文字又有图片的情况?
A: DOM解析方案天然支持这种结构,只要不主动删除父级容器(如<td>),仅移除其中的<img>标签,就能保持表格完整性,测试案例表明,该方法能完美保留表格边框、跨列合并等复杂样式

分享:
扫描分享到社交APP
上一篇
下一篇