无论在原始页面中使用何种编码方法,我都希望从将转换为UTF-8的URL中提取各种数据(或者至少它将适用于大多数源代码编码)。
因此,在查看和搜索了许多讨论和答案之后,我终于得到了以下代码,我用它解析HTML数据两次(一次用于检测编码,另一次用于获取实际数据)。这至少适用于所有已检查的URL。但我认为代码写得不好。
有没有人可以告诉我是否有更好的替代方法可以做同样的事情,或者我是否需要对代码进行任何改进?
<?php
header('Content-Type: text/html; charset=utf-8');
require_once 'curl.php';
require_once 'curl_response.php';
$curl = new Curl;
$url = "http://" . $_GET['domain'];
$curl_response = $curl->get($url);
$header_content_type = $curl_response->headers['Content-Type'];
$dom_doc = new DOMDocument();
libxml_use_internal_errors(TRUE);
$dom_doc->loadHTML('<?xml encoding="utf-8" ?>' . $curl_response);
libxml_use_internal_errors(FALSE);
$metas = $dom_doc->getElementsByTagName('meta');
foreach ($metas as $meta) {
if (strtolower($meta->getAttribute('http-equiv')) == 'content-type') {
$meta_content_type = $meta->getAttribute('content');
}
if ($meta->getAttribute('charset') != '') {
$html5_charset = $meta->getAttribute('charset');
}
}
if (preg_match('/charset=(.+)/', $header_content_type, $m)) {
$charset = $m[1];
} elseif (preg_match('/charset=(.+)/', $meta_content_type, $m)) {
$charset = $m[1];
} elseif (!empty($html5_charset)) {
$charset = $html5_charset;
} elseif (preg_match('/encoding=(.+)/', $curl_response, $m)) {
$charset = $m[1];
} else {
// browser default charset
// $charset = 'ISO-8859-1';
}
if (!empty($charset) && $charset != "utf-8") {
$tmp = iconv($charset,'utf-8', $curl_response);
libxml_use_internal_errors(TRUE);
$dom_doc->loadHTML('<?xml encoding="utf-8" ?>' . $tmp);
libxml_use_internal_errors(FALSE);
}
$page_title = $dom_doc->getElementsByTagName('title')->item(0)->nodeValue;
$metas = $dom_doc->getElementsByTagName('meta');
foreach ($metas as $meta) {
if (strtolower($meta->getAttribute('name')) == 'description') {
$meta_description = $meta->getAttribute('content');
}
if (strtolower($meta->getAttribute('name')) == 'keywords') {
$meta_tags = $meta->getAttribute('content');
}
}
print $charset;
print "<hr>";
print $page_title;
print "<hr>";
print $meta_description;
print "<hr>";
print $meta_tags;
print "<hr>";
print "Memory Peak Usages: " . memory_get_peak_usage()/1024/1024 . " MB";
?>
答案 0 :(得分:1)
你的问题太开放了,我已经投票决定关闭它。但是,我仍然会提供一个答案的存根,希望能指出你正确的方向。
目前,您正在检查字符集的用户定义输入。由于各种原因,这是一个非常非常非常坏的举动:
header("Content-type: text/html; charset=utf-8")
,因为他们听说这是一种很好的做法,而不是实际编码。不考虑这一点将导致UTF-8输出受损DOMDocument
很重要(我最近遇到过这个问题)iconv
双utf-8编码永远不会有趣。我强烈建议使用实用程序解码UTF-8,直到UTF-8扩展字符范围内没有更多实体,然后编码一次而不是依赖iconv或多字节编码。原因很简单:这些都可能弄错。您还可以设置一个错误处理程序来解析DOMDocument错误,以便捕获并重定向loadXML“由于格式错误的XML”而导致错误,这些错误根本与您的字符编码无关。基本上,问题的关键是不要盲目做事。
如果您想要担心需要担心UTF-8的好目标,请解析Google Play的主页。他们发出格式错误的回复(这最初迫使我通过UTF-8-decode-until-nothing-in-the-range方法)。它还将向您显示DOMDocument可能由于各种原因(不仅仅是charset)而失败,并且您需要按照错误来处理它们。
除了大编码snafu之外的其他性能指针包括:
此:
if (preg_match('/charset=(.+)/', $header_content_type, $m)) {
$charset = $m[1];
} elseif (preg_match('/charset=(.+)/', $meta_content_type, $m)) {
太可怕了。您可以使用strpos调用轻松替换它,这将使这一特定ifs的速度提高约5-10倍。
* $metas = $dom_doc->getElementsByTagName('meta');
- 您知道DOMDocument在您使用此方法时将遍历整个DOM,对吗?考虑将XPath查询限制为head
标记(它始终是html的第一个子项,即文档.XPath:/html/head[0]
)
答案 1 :(得分:0)
关于性能,当你完成变量或值时,你应该使用unset();
,即使你要重置它们的值,但是如果你需要你的脚本中的值,则不是。 PHP无法回收内存,并将重用unset命令释放的预分配内存以供将来使用。
您可以做的另一件事是获取大量代码并将其拆分为返回结果值的函数。请记住,除非您正在处理全局变量,否则函数变量和内存会在执行后自动释放。
这些将有助于提高性能和内存利用率。