完美解决All in One SEO Pack对中文支持不友好的问题

发表评论 阅读评论

大家都知道All in One SEO Pack是wordpress的一个搜索引擎优化的插件,但它对中文支持不友好。修改它的代码可以完美支持中文。
All in One SEO对英文支持很好的。因为它只考虑的单字节语言的情况,没有考虑多字节(例如中文等非英文的语言)的情况。

问题介绍

All in One SEO Pack只截取英文空格(" ")之前的内容作为description(描述)的内容,但是我们写中文博客,多数不会在文章中出现英文空格,更别说在开头的恰当位置了,所以中文博客用它就就悲剧了,只生成很短的描述,甚至不生成描述。

解决方法

在{wordpress目录}/wp-content/plugins/all-in-one-seo-pack/aioseop.class.php文件中搜索function trim_excerpt_without_filters方法,类似这样的:

function trim_excerpt_without_filters($text) {
    $text = str_replace(']]>', ']]>', $text);
    $text = preg_replace( '|[(.+?)](.+?[/1])?|s', '', $text );
    $text = strip_tags($text);
    $max = $this->maximum_description_length;

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

    $text = substr($text, 0, $max);
    return trim(stripcslashes($text));
}

使用下面的代码替换掉上面的代码即可。

function trim_excerpt_without_filters($text) {
    $text = str_replace(']]>', ']]&gt;', $text);
    $text = preg_replace( '|[(.+?)](.+?[/1])?|s', '', $text );
    $text = strip_tags($text);
    $max = $this->maximum_description_length;

    if ($max < strlen($text)) {
        while((ord($text[$max]) & 0x80) != 0 && (ord($text[$max]) & 0x40) == 0 &&
                $max > $this->minimum_description_length) {
            $max--;
        }
    }

    $text = substr($text, 0, $max);
    return trim(stripcslashes($text));
}

2013-5-11更新
上面的代码适用于All In One SEO Pack插件的1.x版本,在2.0.3及之后版本中被重新设计了,但是我们依然能够找到并修改之。
在{wordpress目录}/wp-content/plugins/all-in-one-seo-pack/aioseop_class.php文件中搜索function trim_excerpt_without_filters方法,类似这样的:

function trim_excerpt_without_filters( $text, $max = 0 ) {
    $text = str_replace( ']]>', ']]&gt;', $text );
    $text = preg_replace( '|[(.+?)](.+?[/1])?|s', '', $text );
    $text = strip_tags( $text );
    if ( !$max ) $max = $this->maximum_description_length;

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

使用下面的代码替换掉上面的代码即可。

function trim_excerpt_without_filters( $text, $max = 0 ) {
    $text = str_replace( ']]>', ']]&gt;', $text );
            $text = preg_replace( '|[(.+?)](.+?[/1])?|s', '', $text );
    $text = strip_tags( $text );
    if ( !$max ) $max = $this->maximum_description_length;

    if ( $max < $this->strlen( $text ) ) {
        while((ord($text[$max]) & 0x80) != 0 && (ord($text[$max]) & 0x40) == 0 
              && $max > $this->minimum_description_length ) {
            $max--;
        }
    }
    $text = substr( $text, 0, $max );
    return trim( stripcslashes( $text ) );
}

修改后覆盖到空间,description描述信息就会出现了。

2014-8-18更新
如果不想自己修改代码,可以从github下载已经修改好的代码。这里提供2.1.4及更新的所有版本的修改。
如果没有你所需要的版本,请提交issuespr,也可以直接在本页面留言,我将会尽快更新。
注意:修改过的版本以for chinese开头,比如2.1.4版本的为for chinese v2.1.4

解决原理

wordpress的博客多数都是UTF8格式的,那么我们只需要研究下UTF8格式就好了,当然如果使用gbk或者跟utf8不兼容的格式,那么这个方法是不可行的。

UTF-8是一种变长的编码方式。它可以使用1~4个字节表示一个符号(字),根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:

  1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
  2. 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围      | UTF-8编码方式
(十六进制)           | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

那么我们只要以一个字的第一个字节处结束(不包含该字节)就能获取完整的字符串了,也不会有乱码产生。
从上面的编码规则可以看出,如果一个字节的最高位为0,或者前两个高位都为1,那么这个字节一定是一个字的第一个字节。

标签: , , , , ,

  1. | |

    强啊!我顶一个!

  2. | |

    用all in one seo有段日子了,今天发现有些文章可以自动生成描述,有的不行,以为自己网站有问题,研究了半天发现trim_excerpt_without_filters这个函数有问题,搜了一下就找到博主这里了。没想到博主解释的这么深刻,彻底学习了

  3. | |

    我又来了,晕,随意搜索SEO插件没想到又是博主的博客,呵呵,拜访一个

  4. | |

    @glfu
    不是吧,你在哪里搜的,我怎么没搜到呢。

  5. | |

    @Sola
    呵呵,All in one seo Pack这个插件估计是以英语为母语的人,所以兼容多字节的情况,但是对于我们多字节的语言就不友好了。

  6. | |

    插件该更新了!最新版本2.3.3。。找了半天都没找到。。

  7. | |

    @窃窃私语
    抱歉,国庆回家了,没有看到,现在最新版本是2.2.3.1,还没有2.3.3呢,这里是wp的插件地址 https://wordpress.org/plugins/all-in-one-seo-pack/ ,2.2.3.1的中文支持版本可以到git上下载 https://github.com/lite3/all-in-one-seo-pack/releases

  8. | |

    @lite3 我说的是pro版的。。现在这个就行。

    这个中文版开启自动描述后就是会自动截取文章内容没描述了?

    我开启后有些文章没添加Seo信息。但是也没自动添加描述。。

    还有评论没有邮件通知。。

    谢谢了!

  9. | |

    @窃窃私语
    不知道pro版的在哪里下载。
    后台需要勾选自动生成描述的。
    评论邮件通知是说我回复你,你没有收到邮件通知吗?看看有没有在垃圾邮箱里。

  10. | |

    垃圾箱也没有。。你最好测试下。。。

  11. | |

    @lite3
    对了,能参考下你的设置吗?

  12. | |

    @窃窃私语
    是因为mail-stml插件的问题。
    设置自动生成描述:
    1. 【Title Settings】下的【Description Format】中写 %description% 。
    2. 勾选【Advanced Settings】下的【Autogenerate Descriptions】。

  13. | |

    @lite3
    你的noindex怎么设置的。。这个设置不好了收录麻烦。。

  14. | |

    @窃窃私语
    Date Archives, Author Archive, Search Page.

  15. | |

    开启了自动描述,那些没手动添加描述的还是没有描述。。

  16. | |

    @窃窃私语
    你看你的第二篇,《今年双11爆发了~》的描述就是自动生成的。

  17. | |

    @lite3
    我在仪表盘-所有文章 里看的,里面描述还是空白。应该是在浏览文章的时候自动生成描述吧。
    那些手动添加了描述的,他不会自动再生成描述了吧?

  18. | |

    @窃窃私语
    自动生成描述是指在访问文章的时候自动生成,而不放到数据库中,如果已经手动设置了描述,将不再自动生成。

  19. | |

    这个版本的 怎么修改啊 亲

回到顶部