我正在尝试下载一个站点以供脱机查看,这需要我做一些DOM操作(相信我,wget只是没有做我需要做的事情...)。
我发现包含带有异常文本内容标签的网页正在丢弃saveHTML 。
对于某些网址,如果我使用curl读取页面并输出为
echo $contents;
那么一切都很好。
例如,页面的一部分包含以下来源:
<div id="area2516" class="component interaction_component float-none clear-none ">
<div id="area2516">
<script type="text/javascript">
window.bm = window.bm || {};
bm.data = bm.data || [];
bm.data['area2516'] = {};
</script>
<link rel="stylesheet" type="text/css" href="/somecss.css">
<script type="text/javascript" src="somejs.js">
</script>
<script class="main-template" type="text/x-handlebars-template">
<div class="content_area">
<div class="bg_image cf"></div>
{{#each rollovers}}
<div class="rollover_content" style="left: {{x}}; top: {{y}}; display: none;" data-rollover-id="{{id}}">
{{{this.content}}}
</div>
{{/each}}
</div>
<div class="rollover_links">
<ul>
{{#each rollovers}}
<li>
<a class="rollover_link" href="#" data-rollover-id="{{id}}">
{{{link}}}
</a>
</li>
{{/each}}
</ul>
</div>
</script>
<script type="text/javascript">
bm.data['area2516'].assets = {};
bm.data['area2516'].initial_json = '';
</script>
从卷曲响应后的上述回声中可以看到。
现在,如果我这样做
$doc = new DOMDocument();
@$doc->loadHTML($contents);
$xpath = new DOMXpath($doc);
echo $doc->saveHTML();
HTML搞砸了,因此上面的代码变成了这样:
<div id="area2516" class="component interaction_component float-none clear-none ">
<div id="area2516">
<script type="text/javascript">
window.bm = window.bm || {};
bm.data = bm.data || [];
bm.data['area2516'] = {};
</script>
<link rel="stylesheet" type="text/css" href="/somecss.css"> .
<script type="text/javascript" src="/somejs.js"></script>
<script class="main-template" type="text/x-handlebars-template">
<div class="content_area">
<div class="bg_image cf">
</script>
</div>
{{#each rollovers}}
<div class="rollover_content" style="left: {{x}}; top: {{y}}; display: none;" data-rollover-id="{{id}}">
{{{this.content}}}
</div>
{{/each}}
</div>
<div class="rollover_links">
<ul>
{{#each rollovers}}
<li>
<a class="rollover_link" href="#" data-rollover-id="{{id}}">
{{{link}}}
</a>
</li>
{{/each}}
</ul></div>
<script type="text/javascript">
bm.data['area2516'].assets = {};
bm.data['area2516'].initial_json = '';
</script>
很抱歉,这种格式的新编辑器很烦人。关键是,您会看到一些非常重要的区别,但我不确定saveHTML是如何导致对源代码的这种修改。我怀疑这与编码以及模板系统使用的双括号和三括号的特殊性有关,但是尽管尝试使用各种编码参数,但我得到了相同的结果。然后,我想也许与特殊字符,转义有关,但是我只是不确定需要什么函数来阻止saveHTML弄乱输出。
想法?
谢谢
答案 0 :(得分:0)
根据HTML 4规范,您不能将任意文本放入<script>
元素中。 (尽管这个is possible in HTML 5,PHP附带的libxml
解析器并不是那么新。)
如果您正确地转义了元素的内容,则您的代码应该可以按预期工作。
$content = <<< HTML
<div id="area2516" class="component interaction_component float-none clear-none ">
<div id="area2516">
<script type="text/javascript">
window.bm = window.bm || {};
bm.data = bm.data || [];
bm.data['area2516'] = {};
</script>
<link rel="stylesheet" type="text/css" href="/somecss.css">
<script type="text/javascript" src="somejs.js">
</script>
<script class="main-template" type="text/x-handlebars-template">
<div class="content_area">
<div class="bg_image cf"></div>
{{#each rollovers}}
<div class="rollover_content" style="left: {{x}}; top: {{y}}; display: none;" data-rollover-id="{{id}}">
{{{this.content}}}
</div>
{{/each}}
</div>
<div class="rollover_links">
<ul>
{{#each rollovers}}
<li>
<a class="rollover_link" href="#" data-rollover-id="{{id}}">
{{{link}}}
</a>
</li>
{{/each}}
</ul>
</div>
</script>
<script type="text/javascript">
bm.data['area2516'].assets = {};
bm.data['area2516'].initial_json = '';
</script>
HTML;
$doc = new DOMDocument();
$doc->loadHTML($content, LIBXML_HTML_NODEFDTD|LIBXML_HTML_NOIMPLIED);
echo $doc->saveHTML();
输出符合预期:
<div id="area2516" class="component interaction_component float-none clear-none ">
<div id="area2516">
<script type="text/javascript">
window.bm = window.bm || {};
bm.data = bm.data || [];
bm.data['area2516'] = {};
</script>
<link rel="stylesheet" type="text/css" href="/somecss.css">
<script type="text/javascript" src="somejs.js">
</script>
<script class="main-template" type="text/x-handlebars-template">
<div class="content_area">
<div class="bg_image cf"></div>
{{#each rollovers}}
<div class="rollover_content" style="left: {{x}}; top: {{y}}; display: none;" data-rollover-id="{{id}}">
{{{this.content}}}
</div>
{{/each}}
</div>
<div class="rollover_links">
<ul>
{{#each rollovers}}
<li>
<a class="rollover_link" href="#" data-rollover-id="{{id}}">
{{{link}}}
</a>
</li>
{{/each}}
</ul>
</div>
</script>
<script type="text/javascript">
bm.data['area2516'].assets = {};
bm.data['area2516'].initial_json = '';
</script></div></div>
请注意,您的HTML在其他方面无效;重复的id
属性和缺少的结束元素。
答案 1 :(得分:0)
输入甚至看起来都不像HTML
,而是看起来像Twig(或类似的模板)...
需要首先通过模板引擎进行推送,以获得HTML
的输出;
除非通过(array) $rollovers
...在某些情况下不会产生预期的结果。
如果这些不是您自己的模板文件,则可能是下载了错误的URL
...
,另一边的人忘记了阻止访问模板。