PHP:UTF-8字符编码

4
我正在使用cURL爬取一系列的RSS源,然后使用SimpleXML读取并解析RSS数据。排序后的数据随后被插入到MySQL数据库中。
然而,如在http://dansays.co.uk/research/MNA/rss.php上所提到的,我遇到了一些字符显示不正确的问题。
举例来说:
âGuitar Hero: Van Halenâ Trailer And Tracklist Available

NV 10/10/09 – Salt Lake City, UT 10/11/09 – Denver, CO 10/13/09 –

我在将数据插入数据库之前尝试使用htmlentities和htmlspecialchars,但似乎并没有帮助解决问题。

我应该如何解决这个问题?

感谢任何建议。

更新

我尝试了Greg建议的方法,问题仍然存在...

以下是我在PDO中使用SET NAMES的代码:

$dbh = new PDO($dbstring, $username, $password); 

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

$dbh->query('SET NAMES "utf8"');

在将simplexml数据排序并插入数据库之前,我做了一些echo操作,现在我相信这与cURL有关...

下面是我的cURL代码:

$ch = curl_init($url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);

curl_setopt($ch, CURLOPT_HEADER, 0);

curl_setopt($ch, CURLOPT_ENCODING, 'UTF-8');

$data = curl_exec($ch);

curl_close($ch);

$doc = new SimpleXmlElement($data, LIBXML_NOCDATA);

问题已解决

我必须在RSS/HTML页面中设置内容字符集为“UTF-8”以解决此问题。我猜这不是一个真正的修复,因为原始数据中的字符问题仍然存在。期待在PHP6中得到适当的支持!


如果不涉及机密,您能否说一下问题反馈的URL是什么?Curl只返回它所接收到的字节 - 可能是反馈本身有问题。 - user8599
我发现一些我遇到问题的信息源:http://www.telegraph.co.uk/culture/music/rss http://www.metalhammer.co.uk/feed/ http://feedproxy.google.com/~r/smnnews/ http://hangout.altsounds.com/external.php?type=RSS2我将不得不检查它们,因为大约有30个... - Daniel Clark
4个回答

3

您的页面以UTF-8格式提供,所以我会怀疑是数据库的问题。

在进行任何SELECT或INSERT操作之前,请确保连接已经设置为UTF-8 - 在MySQL中:

SET NAMES "utf8"

1
OP正在使用cURL阅读一个RSS源,与数据库无关。 - Marius
请重新阅读问题:“排序后的数据随后被插入到一个mySQL数据库中。” - Greg
1
在myPHPAdmin中的表上已经设置了'utf8_general_ci'。 - Daniel Clark
3
设置表使用的编码方式与您用于与这些表进行交互的编码方式是两个不同的问题。 您可以非常容易地传递MySQL latin1数据,它将在存储之前转换为UTF-8。Greg推荐的SET NAMES utf8命令表示:“我打算使用UTF-8与MySQL进行所有通信。” 或者,另一种说法是:“我将向您(MySQL)提供的数据已经编码为UTF-8。” - VoteyDisciple
正如@VoteyDisciple所说,utf8_general_ci是排序规则 - 它影响某些字符串函数和运算符的工作方式,但不影响连接的字符集。 - Greg
昨天我试图克服一个问题几个小时,但没有网络连接...无法访问SO...像穴居人一样编码。谢谢GREG!他提供了一个快速简单的解决方案。 - Peter Perháč

3

关于CURLOPT_ENCODING的简要说明:它是Accept-Encoding头部,这与字符编码完全不同。支持的接受编码有"identity"、"deflate"和"gzip"。


2

像所有的调试一样,你要先确定问题:

我正在使用 cURL 爬取一组 RSS 订阅源, - 查看导致问题的 RSS 源的 xml(有多个源,因此可能有些源是正确的,而错误的源以不同的方式出错)

接着我使用 SimpleXML 读取和解析 RSS 数据。 - 打印 SimpleXML 读出的字段——它是否正常或者是否出现了问题?

排序后的数据然后被插入到 MySQL 数据库中。 - 打印出导致问题的数据片段的十六进制值(hex(field)), 长度(length(field)) 和字符长度(char_length(field))。

编辑

将订阅源http://hangout.altsounds.com/external.php?type=RSS2放入验证器http://validator.w3.org/feed/。他们将其内容类型声明为 iso-8859-1,但实际的内容(比如引号)是类似于 cp1252 的 - 例如,他们使用字节0x93表示左引号-http://www.fileformat.info/info/unicode/char/201C/charset_support.htm

令人烦恼的是,这在一些工具中并没有显示出来——Firefox似乎能猜到情况并正确显示引号,更重要的是,SimpleXML将0x93转换为utf8,因此它变成了0xc293,这加剧了问题。

编辑 2

让该源读起来更正确的解决方法是在传递给 Simple XML 之前将 "ISO-8859-1" 替换为 "Windows-1252"。它不会100%地起作用,因为结果表明部分内容是 UTF8。

一般的做法是假设你无法让世界上所有人都改正他们的订阅源,就应该将所需的任何解决方案隔离到与发出格式不正确数据的外部系统的接口中,并将纯净的 utf8 传递到您系统的核心。保存一个带有日期的原始外部源的副本,以便您日后记住为什么需要解决方法,将实现解决方法的代码行分离并注释,以便轻松访问和更改,如果外部组织纠正其源(或以不同的方式破坏其源),请再次检查它。不幸的是,您的编程并不是根据规范进行编程,而是根据错误的当前状态进行编程,因此没有永久、干净的解决方案——您能做的最好的就是隔离、文档化和监控。


我已经到了实际编码问题直接来自xml数据本身的地步,正如您在检索到的一些标题中所看到的... http://dansays.co.uk/research/MNA/fetch.raw.php - Daniel Clark

1

这可能与XML序言有关,对于您链接的特定源,它看起来像这样:

<?xml version="1.0" encoding="ISO-8859-1" ?>

据我所知,SimpleXML基于libxml,它会寻找这种类型的内容。我不确定XML文件,但我确定对于HTML字符串,它会寻找指定字符集的元素。
尝试去除XML序言(我曾通过去除HTML 标签解决过类似的问题),并在将数据提供给SimpleXMLElement之前不要忘记utf8_encode()进行编码。

您的帮助确实将我指向了正确的方向,但还没有完全解决我的问题。无论如何,还是谢谢! - Daniel Clark

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