file_get_contents()将UTF-8转换为ISO-8859-1。

3

我正在尝试从yahoo.com获取搜索结果。

但是,file_get_contents()会将UTF-8字符集(yahoo使用的字符集)的内容转换为ISO-8859-1。

尝试以下方法:

$filename = "http://search.yahoo.com/search;_ylt=A0oG7lpgGp9NTSYAiQBXNyoA?p=naj%C5%A1%C5%A5astnej%C5%A1%C3%AD&fr2=sb-top&fr=yfp-t-701&type_param=&rd=pref";

echo file_get_contents($filename);

脚本作为

header('Content-Type: text/html; charset=UTF-8');

或者

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

或者

$er = mb_convert_encoding($filename , 'UTF-8');

或者

$s2 = iconv("ISO-8859-1","UTF-8",$filename );

或者

echo utf8_encode(file_get_contents($filename));

对于获取的网页内容中出现的特殊字符,如 š ť ž 等,直接使用“NOT help”是无法解决的,因为它们会被替换成问号 ???。

我希望能得到任何形式的帮助。


file_get_contents()不会转换任何内容 - Your Common Sense
4个回答

8
这似乎是一个内容协商问题,因为file_get_contents可能会发送一个只接受ISO 8859-1字符编码的请求。
您可以使用stream_context_create创建一个自定义流上下文,明确声明您接受UTF-8,以供file_get_contents使用。
$opts = array('http' => array('header' => 'Accept-Charset: UTF-8, *;q=0'));
$context = stream_context_create($opts);

$filename = "http://search.yahoo.com/search;_ylt=A0oG7lpgGp9NTSYAiQBXNyoA?p=naj%C5%A1%C5%A5astnej%C5%A1%C3%AD&fr2=sb-top&fr=yfp-t-701&type_param=&rd=pref";
echo file_get_contents($filename, false, $context);

有趣的事情,我尝试了“Accept-Charset=utf-8;q=0.7,*;q=0.7”,但是不起作用 :) - Dejan Marjanović
@webarto:值为utf-8;q=0.7,*;q=0.7的内容类似于utf-8,*,可以同等接受任何字符编码。 - Gumbo
太棒了Gumbo!我一直在为URL中的umlauts(München)苦苦挣扎 - 这解决了问题。谢谢! - Craig Morgan

3

file_get_contents 不应该改变字符集。数据作为二进制字符串获取。

当检查您提供的URL时,它提供的是这个头部:

Content-Type: text/html; charset=ISO-8859-1

此外,在正文中:
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">

此外,您不能将UTF-8无损转换为ISO-8859-1并在返回UTF-8时恢复字符。 UTF-8 / Unicode支持更多的字符,因此在第一步中丢失了这些字符。

在浏览器中,情况并非如此,因此您可能只需要提供正确的Accept-Encoding标头以指示Yahoo系统可以接受UTF-8。


你是怎么发现 Content-Type: text/html; charset=ISO-8859-1<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> 的?当我查看该页面的源代码时,我看到 <!doctype html><html lang="en"><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"> - vladinko0
它根据您的位置提供不同的编码,您可以尝试使用俄罗斯代理服务器获取页面。 - Dejan Marjanović

1
$s2 = iconv("ISO-8859-1","UTF-8//TRANSLIT//IGNORE",$filename );

更好的解决方案...
function curl($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_ENCODING, 1);
    return curl_exec($ch);
    curl_close($ch);
}

echo curl($filename);

结果是:文档已经移动到这里。 - vladinko0
@vladinko0,我认为你需要设置CURLOPT_FOLLOWLOCATION,我已经更新了我的回答,请再试一次。 - Dejan Marjanović
现在它加载了页面,但结果与file_get_contents()相同,也就是带有问号。字符集也转换为ISO-8859-1。 - vladinko0
看起来 Yahoo.com 根据用户的 IP(国家)提供不同的页面(字符集)。我已将您的 URL 更改为 http://ru.search.yahoo.com,但它无法工作。也许您可以通过接受字符集标题,拒绝 ISO-8859-1 来实现一些东西... - Dejan Marjanović

1

对于任何调查此问题的人:

我在处理编码问题时学到,很少有php函数可以“神奇地”改变字符串的编码。(这些罕见的例子之一是:

exec($command,$output,$returnVal)

请注意,有效的标头设置如下:

header('Content-Type:text / html; charset = utf-8');

而不是:

header('Content-Type:text / html; charset = UTF-8');

由于我遇到了与您描述的类似的问题,因此正确设置标头就足够了。

希望能帮到你!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接