WP的All-in-One-SEO-Pack插件对中文支持的bug

WordPress的All-in-One-SEO-Pack插件是我所见过的最强大的一款做SEO的插件了,是由uberdose强人打造的。众所周知的是,WordPress本身就在静态URL等方面具有先天的SEO 友好性质,不过在标题、描述、关键词这几个方面仍然显示出一定的不足来。而All-in-One-SEO-Pack插件就可以很好地满足我们的需求。

然而今天通过google sitemap的查看忽然发现我的许多页面没有像预期一样有着分别自动形成的META Description信息,而是都成了默认的网站描述信息了。我马上到具体的页面中去查看,发现description并没有自动生成,莫名地缺失了,所以google只好去采集页面下面标签中的信息,所以才造成了重复。

*** 

那么为什么All-in-One-SEO-Pack没有为通过截取文章前若干文字而产生description呢?

通过仔细阅读代码,我发现了根源所在。

代码截取的时候使用的是如下的方式:

  $max = $this->maximum_description_length;
  if ($max < strlen($text)) {
     while($text[$max] != ' ' && $max > $this->minimum_description_length) {
       $max--;
     }
  }
  $text = substr($text, 0, $max);

其原理是,从一个设定的最大截取字数处开始反向寻找,直到找到一个空格就停止,从而截取到此处。

这种方式似乎让用汉语的人觉得莫名其妙,汉语中传统上基本没有空格一说的(除却避讳、数学表示等情况),而这问题偏偏出在书面语言的差异上面了!

插件的作者是说英语的,而包括英语在内的大多数西方语言都是以空格作为单词与单词的划分依据,所以该处的用法可以保证不会截取到一个完整单词的一小部分。而对于包括中文在内的各类以字作为最小语素的书面语言来说,这种判断方法是完全行不通的。因而要对汉语的书写习惯进行分析。

那么应该怎么处理呢?对于汉语来说,在书面语法上来说,我们是以换行和句号、感叹号等作为完整句意的分割的(有人会说段前空两格,这个嘛,还是用CSS实现自动缩进的好,记起很早时所写的那篇《网络文章中的中文格式问题》了。)然而判断换行还比较容易,而判断句号等符号会存在一定困难(从下文涉及判断汉字时即可看出)。

但事实上来说,我们干嘛非要去按照自然语言来截取呢?我们是为了提供给搜索引擎一个参考的语句,而这语句其实是用来提供关键词的,即使是最后搜索引擎用来展现给用户的也不过是截断的语句部分。所以不如就是先寻找换行之类,如果找不到则按照最大长度直接截取。

然而直接截取的时候又遇到问题了,出现了FFFD情况,出现了一个框中有FFFD字样。这显然是由于对汉字的强行截断而产生的。我也想当然地以为汉字在此处是以两个字符来存储的,也在网上查到了很多方法来判断,可惜总是失败了,没有办法,我只好读取出来数据,查看汉字的表示情况,才发现其实在此处汉字就是以UTF-8形式来存储的,每个汉字占三个字节!

那么就开始对All-in-One-SEO-Pack插件的all_in_one_seo_pack.php文件进行修改,一共要修改三处。第一处是找到

trim_excerpt_without_filters($text)

函数,将其整体改为:

function trim_excerpt_without_filters($text) {
  $text = str_replace(']]>', ']]>', $text);
  $text = strip_tags($text);
  $max = $this->maximum_description_length;
  if ($max < strlen($text)) {
    while($text[$max] != ' ' && text[$max] != '\n' && $max > $this->minimum_description_length) {
      $max--;
    }
  }
  if($max == $this->minimum_description_length) {
    $max = $this->maximum_description_length;
  }
  if($text[$max - 1] == '\r') {
    $max--;
  }
  if(ord($text[$max]) > 0x7F && ord($text[$max]) < 0xC0)
  {
    while(ord($text[$max]) <= 0xC0)
      $max--;
  }
  $text = substr($text, 0, $max);
  return trim(stripcslashes($text));
}

第二处是开头处的

$maximum_description_length

$minimum_description_length

设置,要注意的是,一般来说建议META Description信息在100~150字最佳,然而每个汉字又占3个字节,所以要乘上三倍。不过需要注意的是,如果自己的文章开头处会有英文,那么就会有结结实实的300个字符了,要慎重。

  var $maximum_description_length = 300;
  var $minimum_description_length = 80;

第三处是代码中的一句

if (isset($description) && (strlen($description) > this->minimum_description_length) && !(is_home() && is_paged())) {

这里我觉得当所得strlen($description)等于$this->minimum_description_length

也是有可能出现的恰好情况啊,为什么用“>”而忘记了等于的情况呢?所以我觉得应当改成:

if (isset($description) && (strlen($description) >= this->minimum_description_length) >> !(is_home() >> is_paged())) {

2008年01月14日 18:35:28更新:
今天发现数据丢了,应该是和今天CPH服务器的数据库有关。第一,我的这篇新文章页面还没有来得及被Google收录快照;第二,即使收录了,我也在之前统一设置为了不拍快照;第三,我的每天深夜12点自动备份数据库到邮箱的功能正常运行了,可数据是在昨天12点之前丢的,我总不能没小时都备份吧?第四,Feed已经被抓取了,可我一直没有舍得用插件实现全文RSS输出。最后造成的情况是,这篇文章我基本需要重写。T_T


4 Comments:

  1. Pingback: WordPress的All-in-One-SEO插件对中文支持的bug | 猫言猫语

  2. 我的Description出现一串串的空格符号>o<。
    原来是这样的,谢谢博主 ^o^.

  3. 现在放在aioseop.class.php下了吧?

  4. Pingback: 修改wordpress插件All in One SEO支持中文截断 | 乾坤 Blog

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*