[英]Detect Encoding and Convert Everything to UTF-8 with PHP
我想从将要转换为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";
?>
您的问题过于开放,我已投票决定将其关闭。 但是,我仍然会提供一个答案的存根,希望能为您指明正确的方向。
目前,您正在检查用户定义的字符集输入。 由于各种原因,这是一个非常非常非常糟糕的举动:
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解码直到一切正常的方法)。 它还将向您显示DOMDocument可能由于多种原因而失败-不仅是字符集-而且您需要按照错误进行处理。
除了大编码之外,其他性能指标还包括:
这个:
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]
)
关于性能,您应该使用unset();
当您完成变量或值的设置后,即使您要重设它们的值,但如果您在脚本中更进一步需要该值,也不需要这样做。 PHP无法回收内存,并将重用unset命令释放的预分配内存,以备将来使用。
您可以做的另一件事是占用大量代码,并将其拆分为返回结果值的函数。 请记住,除非您使用全局变量,否则函数变量和内存在执行后会自动释放。
这些将有助于性能和内存利用率。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.