PHP saveHTML 函数没有正确保存 HTML

Posted

技术标签:

【中文标题】PHP saveHTML 函数没有正确保存 HTML【英文标题】:PHP saveHTML function is not saving HTML properly 【发布时间】:2017-02-14 07:39:27 【问题描述】:

我一直在尝试使用 php 保存 webpage 的一部分的源代码。当我提取整个网页的内容时,源代码顺序被保留但是当我尝试使用获取部分文档时

$dom = new DOMDocument;
$dom->loadhtml($webpage);
$xpath = new DOMXPath($dom);

$query_tag = "//div[contains(@class, 'class-name')]";
$result = $dom->saveHTML($xpath->query($query_tag)->item(0));

脚本标签搞砸了。到目前为止,这是唯一出现此问题的网站。 saveHTML 函数是否有一些我不知道的限制?

这是我应该收到的:

<div id="sponsored-category-header" class="page-header sponsored-category-header clear"> <script type="text/javascript">jQuery(document).ready(function($) 
        var cat_head_params = "sponsor":"SEO PowerSuite","sponsor_logo":"https:\/\/www.searchenginejournal.com\/wp-content\/plugins\/abm-sej\/includes\/category-images\/SPS_128.png","sponsor_text":"<div class=\"taxonomy-description\">Dominate Google local search results with ease! Get your copy of SEO PowerSuite and keep <a rel=\"nofollow\" href=\"http:\/\/sejr.nl\/PowerSuite-2016-5\" onClick=\"__gaTracker('send', 'event', 'Sponsored Category Click Var 1', 'Local Search', 'SEO PowerSuite');\" target=\"_blank\">your local SEO strategy<\/a> up to par.<\/div>","logo_url":"http:\/\/sejr.nl\/PowerSuite-2016-5","ga_labels":["Local Search","SEO PowerSuite"]            
        $('#sponsored-category-header').append('<div class="sponsored-category-logo"></div>');
                     $('#sponsored-category-header .sponsored-category-logo').append(' <a rel="nofollow" href="'+cat_head_params.logo_url+'" onClick="__gaTracker(\'send\', \'event\', \'Sponsored Category Click Var 1\', \''+cat_head_params.ga_labels[0]+'\', \''+cat_head_params.ga_labels[0]+'\');" target="_blank"><img class="nopin" src="'+cat_head_params.sponsor_logo+'"   /></a>');
                                   $('#sponsored-category-header').append('<div class="sponsored-category-details"></div>');
         $('#sponsored-category-header .sponsored-category-details').append('<h3 class="page-title sponsored-category-title">'+cat_head_params.sponsor+'</h3>');
         $('#sponsored-category-header .sponsored-category-details').append(cat_head_params.sponsor_text);


);</script> </div>

这是我实际得到的:

<div id="sponsored-category-header" class="page-header sponsored-category-header clear"> <script type="text/javascript">jQuery(document).ready(function($) 
        var cat_head_params = "sponsor":"SEO PowerSuite","sponsor_logo":"https:\/\/www.searchenginejournal.com\/wp-content\/plugins\/abm-sej\/includes\/category-images\/SPS_128.png","sponsor_text":"<div class=\"taxonomy-description\">Dominate Google local search results with ease! Get your copy of SEO PowerSuite and keep <a rel=\"nofollow\" href=\"http:\/\/sejr.nl\/PowerSuite-2016-5\" onClick=\"__gaTracker('send', 'event', 'Sponsored Category Click Var 1', 'Local Search', 'SEO PowerSuite');\" target=\"_blank\">your local SEO strategy<\/a> up to par.<\/div>","logo_url":"http:\/\/sejr.nl\/PowerSuite-2016-5","ga_labels":["Local Search","SEO PowerSuite"]            
        $('#sponsored-category-header').append('<div class="sponsored-category-logo"></script>


</div>');
                     $('#sponsored-category-header .sponsored-category-logo').append(' <a rel="nofollow" href="'+cat_head_params.logo_url+'" onclick="__gaTracker(\'send\', \'event\', \'Sponsored Category Click Var 1\', \''+cat_head_params.ga_labels[0]+'\', \''+cat_head_params.ga_labels[0]+'\');" target="_blank"><img class="nopin" src="'+cat_head_params.sponsor_logo+'"  ></a>');
                                   $('#sponsored-category-header').append('<div class="sponsored-category-details"></div>');
         $('#sponsored-category-header .sponsored-category-details').append('<h3 class="page-title sponsored-category-title">'+cat_head_params.sponsor+'</h3>');
         $('#sponsored-category-header .sponsored-category-details').append(cat_head_params.sponsor_text);


    ); </div>

如果你错过了,结尾的script 标签已经上移了几行。

为了清楚起见,我不是在谈论渲染的 HTML。我说的是提出请求后得到的实际源代码。任何有关如何解决此问题的帮助将不胜感激。

我知道函数 saveHTML 导致了这个问题,因为当我通过 PHP 回显整个页面时,每个标签都在正确的位置。

【问题讨论】:

DOMDocument 是一个合适的 HTML 解析器,因此它无法处理您经常在野外发现的无效标签汤。就像您的浏览器一样,它会尽力修复 HTML。 @ÁlvaroGonzález 所以,$dom-&gt;loadHTML($webpage); 之后的源代码搞砸了? 正确。我没有机会检查该网站,但是,如果有无效标记(我不是说这里是否是这种情况,因此我留下评论而不是答案),它会立即修复因为 PHP 需要使用文档树的内存表示进行操作(正如我所说,这是任何浏览器所做的)。源代码仅此而已,一个 source 我在您感兴趣的部分的页面上没有看到任何无效的内容,但如果没有首先分解流程并检查每个步骤以消除 @,我会犹豫专门责怪 saveHTML首先是 987654330@、DOMXPathquery 谢谢@LinuxDisciple 查询怎么会搞砸?这是我使用//div[contains(@class, 'post-data')] 的查询。它得到第一个结果,其中包含除脚本标记之外的其他标记。有什么方法可以检查loadHTMLDOMXPath 是否是这里的罪魁祸首? 【参考方案1】:

首先,您的代码应该会触发大量警告,如下所示:

警告:DOMDocument::loadHTML(): htmlParseEntityRef: 期待 ';'在 实体 警告:DOMDocument::loadHTML():意外的结束标签: strong Entity 警告:DOMDocument::loadHTML(): Tag header 在实体中无效

这是对通用 HTML 的预期(并且此页面的代码也不是特别糟糕),但您甚至没有提到它,这让我怀疑您可能没有在您的开发框中启用错误报告。

此外,该页面包含大量 JavaScript,DOMDocument 只是一个 HTML 解析器。

这样,我们可以清楚地了解正在发生的事情。由于DOMDocument 不是一个成熟的浏览器,它不理解JavaScript 代码。这意味着它会检测到&lt;script&gt; 标签,但它不会将其内容作为 JavaScript 处理——它只是寻找一个结束标签,他找到的第一个标签是这样的:

$('#sponsored-category-header').append('<div class="sponsored-category-logo"></div>');
                                                                             ^^^^^^

它不知道它是一个 JavaScript 字符串,应该被忽略。相反,它认为关闭了错误的标签,因此它尝试修复技术上无效的 HTML 并添加 missing &lt;/script&gt; 标签。

出于这个确切原因,&lt;script&gt;...&lt;/script&gt; 标记集传统上是这样编写的:

<script type="text/javascript"><!--
var foo = '<p>Escaped end tag<\/p>';
//--></script>

...所以不知道 JavaScript 的用户代理可以安全地忽略整个标签(嘿,这不过是一个很好的旧 HTML 注释)。然而,现在它几乎被普遍认为是不好的做法,因为“所有浏览器都理解 JavaScript”。

最后说明:DOM 扩展可能知道&lt;script&gt; 标记,并且知道其中不允许有其他标记。这就解释了为什么不考虑内部开头的标签。

【讨论】:

谢谢阿尔瓦罗 :)。这就解释了!

以上是关于PHP saveHTML 函数没有正确保存 HTML的主要内容,如果未能解决你的问题,请参考以下文章

R-Shiny:如何显示使用 saveHTML() 函数创建的动画和控件?

如何查看 saveHTML 输出(“HTML 文件创建于:index.html”)?

使用 DOMDocument->saveHTML() 将实际 Unicode 字符自动转换为数值

PHP之:析构函数

将 HTML 5 画布保存到 Chrome 中的文件?

PHP DOMDocument - 获取 BODY 的 html 源代码