使用PHP中的domdocument替换HTML字符串中某个元素中的内容
使用正则表达式
比如我有一个html文件,我要获取第一个script标签中的JS字符串。
$indexHtml = file_get_contents('index.html');
$pattern = '/<script[^>]*>(.*?)<\/script>/is';
preg_match($pattern, $indexHtml, $match);
var_dump($match);
如果使用正则表达式进行替换的话,就会出现问题:使用preg_replace会将字符串中匹配到的每个结果都替换!
$pattern = '/<script[^>]*>(.*?)<\/script>/is';
// 替换函数
function replaceScriptContent($matches) {
// 这里可以处理$matches[1]中的内容,它是<script>标签内的内容
// 作为示例,我们简单地将其替换为空字符串
return '<script type="text/javascript">/* Script content removed */</script>';
}
// 执行替换
$newHtmlContent = preg_replace_callback($pattern, 'replaceScriptContent', $indexHtml);
// 输出结果
echo $newHtmlContent;
preg_replace_callback
函数用于执行替换操作。它接受一个正则表达式模式和一个回调函数,并返回替换后的字符串。回调函数replaceScriptContent
用于处理每个匹配到的<script>
标签的内容。
使用正则表达式来解析或修改HTML通常不是一个好主意,因为HTML结构可以非常复杂,且正则表达式在处理嵌套标签时容易出错。在大多数情况下,使用专门的HTML解析库(如DOMDocument)是更好的选择。
DOMDocument
如果你需要处理复杂的HTML文档,使用HTML解析库(如DOMDocument)是更好的选择。下面是一个使用DOMDocument的例子:
$dom = new DOMDocument();
@$dom->loadHTML($htmlContent, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$scripts = $dom->getElementsByTagName('script');
foreach ($scripts as $script) {
// 你可以在这里处理$script节点的内容
// 例如,移除内容或替换为其他内容
$script->nodeValue = '/* Script content removed */';
}
$newHtmlContent = $dom->saveHTML();
echo $newHtmlContent;
在这个例子中,DOMDocument被用来加载HTML内容,然后遍历所有的<script>
标签,修改它们的内容。使用DOMDocument可以更安全、更可靠地处理HTML。
如果你只想要保存特定的节点,你可以通过getElementById
、getElementsByTagName
或其他 DOM 方法获取该节点,然后将其传递给saveHTML
方法:
$node = $dom->getElementById('myNodeId'); // 假设你有一个ID为myNodeId的元素
echo $dom->saveHTML($node); // 仅输出该节点的HTML内容
但是目前发现vue打包后的文档,获取后会被转义。类似于下面这种情况:
<title>啊啊啊啊</title>
尝试使用下面的方式处理,没有效果,待后续更新,仅做参考:
<?php
$htmlContent = '<html>
<head>
<title>测试页面</title>
</head>
<body>
<h1>欢迎来到测试页面</h1>
<p>这是一个段落。</p>
</body>
</html>';
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true; // 格式化输出
libxml_use_internal_errors(true); // 忽略加载HTML时产生的错误
$dom->loadHTML($htmlContent, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_clear_errors(); // 清除错误
echo $dom->saveHTML(); // 输出整个文档的HTML,汉字不会被转义
?>
解决DomDocument中汉字被转义
解决方式来源于知乎:https://www.zhihu.com/question/20122148
我也遇到相同的问题,解决如下:
使用下面这行代码:
`$doc->saveHTML($doc->documentElement)`
而不是
`$doc->saveHTMLFile('filepath.html');`
最终解决代码如下:
// 假设最终处理得到的信息是这些
$userInfo = [
'user_id' => 1234,
'user_phone' => 13068574566
];
$userInfoJsVar = 'window.userInfo = ' . json_encode($userInfo, JSON_UNESCAPED_UNICODE) . ';';
// 对结构进行调整 获取第一个script标签,并添加上验证后的用户相关信息,与原本信息一起渲染在模板的html页面中
$indexHtml = file_get_contents('index.html');
// 检查字符串是否已经是UTF-8编码
$encoding = mb_detect_encoding($indexHtml, "UTF-8, ISO-8859-1, GBK");
// 如果不是UTF-8编码,则转换编码为UTF-8
if ($encoding != "UTF-8") {
$indexHtml = mb_convert_encoding($indexHtml, "UTF-8", $encoding);
}
$dom = new DOMDocument('1.0', 'UTF-8');
if(!@$dom->loadHTML($indexHtml, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)) {
exit('加载模板遇到错误');
}
$scripts = $dom->getElementsByTagName('script');
// 对第一个script中内容修改$scripts[0]也行
$scripts->item(0)->nodeValue = $userInfoJsVar;
// 传递的参数是解决汉字被转义问题的核心
$resultHtml = $dom->saveHTML( $dom->documentElement );
echo $resultHtml;
domDocument基本使用
从PHP5开始,PHP就为我们提供了一个强大的解析和生成XML相关操作的类,也就是我们今天要讲的 DOMDocument 类。
创建一个新的文本节点
$content = $dom->createTextNode($text);
假设我们有一个已存在的元素$element,我们将$content作为其子节点
$element = $dom->getElementById('some-id');
$element->appendChild($content);
创建一个元素
$node1 = $dom->createElement('First', 'This is First Node.');
生成div 和 p 并将p插入到div中,将div插入到文档中
$xml = new DOMDocument('1.0', 'UTF-8');
$wrapper = $xml->createElement('div', 'this is text in div');
$wrapper->setAttribute('class', 'wrapper');
$inner = $xml->createElement('p', 'text in p');
$inner->setAttribute('class', 'inner');
$wrapper->appendChild($inner);
$xml->appendChild($wrapper);
print $xml->saveHTML();
// 输出结果
// <div class="wrapper">this is text in div<p class="inner">text in p</p></div>
输出xml与html大同小异
// 生成一个XML文档
$xml = new DOMDocument('1.0', 'UTF-8');
$node1 = $xml->createElement('First', 'This is First Node.');
$node1->setAttribute('type', '1');
$node2 = $xml->createElement('Second');
$node2->setAttribute('type', '2');
$node2_child = $xml->createElement('Second-Child', 'This is Second Node Child.');
$node2->appendChild($node2_child);
$xml->appendChild($node1);
$xml->appendChild($node2);
print $xml->saveXML();
/* 输出结果
<?xml version="1.0" encoding="UTF-8"?>
<First type="1">This is First Node.</First>
<Second type="2"><Second-Child>This is Second Node Child.</Second-Child></Second>
*/
获取某个元素的name、src属性
$inputSearch = $doc->getElementById('kw');
echo $inputSearch->getAttribute('name');
// 获取所有图片的链接
$allImageLinks = [];
$imgs = $doc->getElementsByTagName('img');
foreach($imgs as $img){
$allImageLinks[] = $img->getAttribute('src');
}
可以使用parse_url对链接进行分析,返回一个数组
parse_url('http://www.baidu.com/xxxxx');
// Array
// (
// [host] => www.baidu.com
// [path] => /img/baidu_jgylogo3.gif
// )
从外层中删除内层p
$wrapper->removeChild($inner);
// <div class="wrapper">this is text in div</div>
从文档中删除外层
$xml->removeChild($wrapper);