Symfony Dom 抓取工具在模板中缺少结束标记
Symfony Dom Crawler missing closing tag in template
我使用 Symfony DOM 爬虫读取并保存包含模板的 HTML 文档。但是模板中缺少结束 HTML 标记。这是一个例子:
<?php
$htmlString = <<<'HTML'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Title</h1>
<script id="my-template" type="text/template">
<div>{{ Name }}</div>
</script>
</body>
HTML;
$crawler = new Crawler($htmlString);
$output = join(
$crawler->filterXPath('//body')->each(
function (Crawler $node, $i) use ($htmlString) {
return $node->html();
}
)
);
我希望是这样的:
<h1>Title</h1>
<script id="my-template" type="text/template">
<p>Hello</p>
<div>{{ Name }}</div>
</script>
但我得到:
<h1>Title</h1>
<script id="my-template" type="text/template">
<p>Hello
<div>{{ Name }}
</script>
您知道为什么 DOM 抓取工具会省略结束标记吗?
我已经进行了一些调试并使用以下代码隔离了这个问题(因为 Crawler 使用 DOMElement
个对象):
$htmlString = <<<'HTML'
<script id="my-template" type="text/template">
<div> Name </div>;
</script>
HTML;
$el = new \DOMDocument();
libxml_use_internal_errors(true);
$el->loadHTML($htmlString);
echo $el->saveHTML($el);
Ouputs(doctype,html
和head
自动添加,但这里不重要):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><script id="my-template" type="text/template">
<div> Name ;
</script></head></html>
如您所见,它在 script
.
内的结束标记中给出了类似的问题
如果你注释掉 libxml_use_internal_errors(true);
那么你会得到一个错误:
DOMDocument::loadHTML(): Unexpected end tag : div in Entity, line: 2
我也对这个错误进行了一些研究,发现它是 LibXML2 库中的一个相当老的错误,严格来说并不是 PHP 问题:
https://bugs.php.net/bug.php?id=52012
我在 PHP 7.0.6 上遇到了这个问题,所以我想它仍然根本没有解决。
一般来说,它看起来像是关于通过 libxml 库解析标记,因此您将不得不要么不使用 Crawler,要么不要将 HTML 模板放在脚本标记中。解决方案可能因您要实现的目标而异。
我使用 Symfony DOM 爬虫读取并保存包含模板的 HTML 文档。但是模板中缺少结束 HTML 标记。这是一个例子:
<?php
$htmlString = <<<'HTML'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Title</h1>
<script id="my-template" type="text/template">
<div>{{ Name }}</div>
</script>
</body>
HTML;
$crawler = new Crawler($htmlString);
$output = join(
$crawler->filterXPath('//body')->each(
function (Crawler $node, $i) use ($htmlString) {
return $node->html();
}
)
);
我希望是这样的:
<h1>Title</h1>
<script id="my-template" type="text/template">
<p>Hello</p>
<div>{{ Name }}</div>
</script>
但我得到:
<h1>Title</h1>
<script id="my-template" type="text/template">
<p>Hello
<div>{{ Name }}
</script>
您知道为什么 DOM 抓取工具会省略结束标记吗?
我已经进行了一些调试并使用以下代码隔离了这个问题(因为 Crawler 使用 DOMElement
个对象):
$htmlString = <<<'HTML'
<script id="my-template" type="text/template">
<div> Name </div>;
</script>
HTML;
$el = new \DOMDocument();
libxml_use_internal_errors(true);
$el->loadHTML($htmlString);
echo $el->saveHTML($el);
Ouputs(doctype,html
和head
自动添加,但这里不重要):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><script id="my-template" type="text/template">
<div> Name ;
</script></head></html>
如您所见,它在 script
.
如果你注释掉 libxml_use_internal_errors(true);
那么你会得到一个错误:
DOMDocument::loadHTML(): Unexpected end tag : div in Entity, line: 2
我也对这个错误进行了一些研究,发现它是 LibXML2 库中的一个相当老的错误,严格来说并不是 PHP 问题:
https://bugs.php.net/bug.php?id=52012
我在 PHP 7.0.6 上遇到了这个问题,所以我想它仍然根本没有解决。
一般来说,它看起来像是关于通过 libxml 库解析标记,因此您将不得不要么不使用 Crawler,要么不要将 HTML 模板放在脚本标记中。解决方案可能因您要实现的目标而异。