使用PHP检测编码并将所有内容转换为UTF-8
我想从URL中提取各种数据,这些数据将被转换为UTF-8,而不管原始页面中使用的编码方法是什么(或者至少它可以用于大多数源代码) 因此,在查看和搜索了许多讨论和答案之后,我最终得到了以下代码,我使用这些代码两次解析HTML数据(一次用于检测编码,第二次用于获取实际数据)。这至少对所有已检查的URL有效。但我认为代码编写得很糟糕 有没有人能告诉我是否有更好的替代方案来做同样的事情,或者我是否需要对代码进行任何改进使用PHP检测编码并将所有内容转换为UTF-8,php,unicode,encoding,domdocument,php-5.3,Php,Unicode,Encoding,Domdocument,Php 5.3,我想从URL中提取各种数据,这些数据将被转换为UTF-8,而不管原始页面中使用的编码方法是什么(或者至少它可以用于大多数源代码) 因此,在查看和搜索了许多讨论和答案之后,我最终得到了以下代码,我使用这些代码两次解析HTML数据(一次用于检测编码,第二次用于获取实际数据)。这至少对所有已检查的URL有效。但我认为代码编写得很糟糕 有没有人能告诉我是否有更好的替代方案来做同样的事情,或者我是否需要对代码进行任何改进 <?php header('Content-Type: text/html;
<?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";
?>
关于性能,您应该使用
unset()代码>当您处理完变量或值时,即使您要重置它们的值,但如果您需要脚本下一步的值,则不需要。PHP无法回收内存,将重用从unset命令释放的预分配内存以供将来使用
您可以做的另一件事是将大量代码分割成返回结果值的函数。请记住,函数变量和内存在执行后会自动释放,除非您使用的是全局变量
这些将有助于提高性能和内存利用率。关于性能,您应该使用unset()代码>当您处理完变量或值时,即使您要重置它们的值,但如果您需要脚本下一步的值,则不需要。PHP无法回收内存,将重用从unset命令释放的预分配内存以供将来使用
您可以做的另一件事是将大量代码分割成返回结果值的函数。请记住,函数变量和内存在执行后会自动释放,除非您使用的是全局变量
这些将有助于提高性能和内存利用率。你的问题太开放了,我投票决定结束它。然而,我仍然会提供一个答案的存根,希望它能为你指明正确的方向
目前,您正在检查字符集的用户定义输入。这是一个非常非常糟糕的举动,原因有很多:
- 小型网站上的大多数站长只会
标题(“内容类型:text/html;charset=utf-8”)
,因为他们听说这是一种很好的做法,没有实际编码。不考虑这一点将导致UTF-8输出损坏
- 有些站长的做法正好相反:他们不设置头,他们的Web服务器输出ISO-8859-1头,尽管采用UTF-8编码。从页面上可以明显看出,这并不重要-这对
DOMDocument
很重要(我最近遇到过这个问题)
iconv
双utf-8编码从来都不好玩
我强烈建议使用实用程序对UTF-8进行解码,直到UTF-8扩展字符范围内不再有实体,然后编码一次,而不是依赖iconv或多字节编码。原因很简单:这些可能会出错。您还可以设置一个错误处理程序来解析DOMDocument错误,以便捕获并重定向loadXML“由于XML格式错误而失败”错误,这与您的字符编码完全无关。基本上,解决问题的关键是不要盲目做事
如果你想在需要担心UTF-8的地方找到好的目标,请解析GooglePlay的主页。他们发送了格式错误的回复(这就是最初迫使我采用UTF-8-decode-until-nothing-is-in-the-range方法的原因)。它还将告诉您,DOMDocument可能由于各种原因而失败——不仅仅是字符集——并且您需要遵循错误来处理它们
除此之外的其他性能指标包括:
- 将代码分割成结果函数。这里有很多重复——学习使用函数,以避免多次明确地编写相同的核心函数
- 这:
if(preg_match('/charset=(.+)/',$header_content_type,$m)){
$charset=$m[1];
}elseif(preg_match('/charset=(.+)/',$meta_content_type,$m)){
太可怕了。你可以很容易地用strps调用替换它,这将使这组ifs的速度提高5-10倍。
*代码$> $METAs= $DOMDOCK-> GETELMENTSMEBYTAGNOTY(“META”); >您知道当使用此方法时DOMDOX将贯穿您的整个DOM,对吗?考虑将XPath查询限制为<代码>头>代码>标签(它总是HTML的第一个孩子,即文档.XPath:<代码> /HTML/HORD(0)< /代码>)你的问题太开放了,我投票决定结束它。不过,我还是会提供一个答案的存根,希望能为你指明正确的方向
目前,您正在检查字符集的用户定义输入。这是一个非常非常糟糕的举动,原因有很多:
- 小型网站上的大多数站长只会
标题(“内容类型:text/html;charset=utf-8”)
,因为他们听说这是一种很好的做法,没有实际编码。不考虑这一点会导致utf-8输出被破坏
- 有些站长的做法正好相反:他们不设置标题,他们的Web服务器输出ISO-8859-1标题,尽管采用UTF-8编码。显然,在页面上,这并不重要-这对于
DOMDocument
(我最近遇到过这个问题)
iconv
双utf-8编码从来都不好玩
我强烈建议使用实用程序对UTF-8进行解码,直到UTF-8扩展字符范围内没有更多的实体,然后编码一次,而不是依赖iconv或多字节编码。原因很简单:这可能会出错。您还可以设置错误处理程序来解析DOMDocument错误,以便捕获和重定向他加载了xml“f”