Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/242.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP检测编码并将所有内容转换为UTF-8_Php_Unicode_Encoding_Domdocument_Php 5.3 - Fatal编程技术网

使用PHP检测编码并将所有内容转换为UTF-8

使用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;

我想从URL中提取各种数据,这些数据将被转换为UTF-8,而不管原始页面中使用的编码方法是什么(或者至少它可以用于大多数源代码)

因此,在查看和搜索了许多讨论和答案之后,我最终得到了以下代码,我使用这些代码两次解析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";
?>

关于性能,您应该使用
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”