coolcfan Press从建立开始,一直使用 press.coolcfan.org/category/postname 这样的永久链接结构,比如我上一篇文章《从字符到LOGO[3]》,其永久链接是:http://press.coolcfan.org/notes/design/from-chars-to-logo-chapter-three。这样的地址有着良好的可读性,对搜索引擎也比较友好,但是,经过半年多的使用,我发现这种格式并不适合我。我是一个比较喜欢纠结分类方法的人,在这半年多中,我经常修改coolcfan Press的日志分类,包括分类的显示名(在分类列表中显示)和缩略名(用于永久链接),这就带来一个副作用——每当我修改分类的时候,都会使这个分类下一部分文章的永久链接发生变化,不可避免地会产生一些404(实际上日志却还在,只是链接改了),甚至导致搜索引擎的惩罚。我是个比较懒的人,想要一劳永逸,修改永久链接结构是最简单的方式。

好了,也许你已经看出来了,上面这段话在逻辑上有一点点毛病:如果我直接改永久链接结构的话,那岂不是所有文章原先的链接都会失效,岂不是会被搜索引擎惩罚得更狠?事实正是如此。不过,解决方法还是有的,那就是——地址转向!

实际上,Wordpress本身就有提供地址转向功能。著名的插件Redirection所使用的默认转向方式,就是Wordpress内置的转向方式。这种方式设置起来比较简单,直接在Redirection里面添加规则即可——你可以一条一条地添加,也可以写一个正则式进行批量匹配,真的是相当方便。

另一种转向方式,则是LAMP主机的优势——Apache提供了一个叫做.htaccess的文件,用户可以在其中自行写入各种脚本,包括301转向脚本。我的空间正是基于LAMP的,我的空间提供者也强烈推荐我使用.htaccess。所以我决定使用.htaccess来解决coolcfan Press的转向问题。

好吧,好吧,我承认,这是一篇教程,前面写了好多废话,现在终于开始了,你一定等不及了吧?不过接下来还是有很多废话,因为这篇教程是以聊天的形式呈现的——我会将我和我的空间提供者ICEST的聊天记录奉上,让大家清楚地看到,从一开始到最后搞定的整个曲折历程。

修改永久链接的曲折历程,从这里开始。

声明:这不等于我和ICEST的真实聊天内容,为了方便阅读,我进行了一定的修改。

coolcfan
想改博客永久链接结构又想保证访客访问旧链接能转向,哪个插件好?(WP2.8)

ICEST
.htaccess,只能改了以后用301重定向吧,对于搜索收录是过段时间会变成新的了,对于别的地方引用的,要一直保留重定向才能让之前的链接继续能访问到

coolcfan
嗯,重定向,我要的就是这个

ICEST
重定向就用.htaccess,和wp无关
你自己得找到url变化规则,写一个rewrite,然后设置301重定向

coolcfan
htaccess里面要写正则式吧,
我原来是/%category%/%postname%这种格式,
现在想改成/%postname%这种,
这正则怎么匹配呢……

ICEST
^/[^/]+/(.*)$ /$1 [R=301]

coolcfan
这句是什么意思

ICEST
匹配第一个 [非/]匹配N次 / 随意字符 重写为 /随意字符。

coolcfan
这样就可以将
http://press.coolcfan.org/notes/design/from-chars-to-logo-chapter-three 这样的地址重写为
http://press.coolcfan.org/from-chars-to-logo-chapter-three 这样的了么?

ICEST
有两级目录?

coolcfan
是啊……有的文章是两级,有的是一级……

ICEST
那还得加个RewriteRule ^(?:[^/]+/)+(.*)$ /$1 [R=301]
前面是匹配,后面$1是引用,
RewriteRule ^(?:[^/]+/)+([^/]+)$ /$1 [R=301,L],这样吧,别死循环了

coolcfan
竟然成功了,但是这么玩还是会出乱子,这个正则式把所有二级目录全干掉了
比如press.coolcfan.org/wp-admin/ssssssssssssssssssss….

ICEST
那前面加一句 RewriteCond %{REQUEST_FILENAME} !-f

coolcfan
电脑没电了,这个明天继续研究~~

ICEST
好 88

第二天……

coolcfan
icest在不

ICEST

coolcfan
我总结了一下,可能受到rewriterule影响的地方举例:

http://press.coolcfan.org/wp-admin/index.php,wp-admin会被干掉,加了昨晚最后一条可解决;

http://press.coolcfan.org/page/2,page会被干掉;

http://press.coolcfan.org/notes/design/from-chars-to-logo-chapter-three/comment-page-1#comment-825,“notes/design/from-chars-to-logo-chapter-three/”会被干掉,实际只需要干掉notes/design/即可;

http://press.coolcfan.org/topics/notes/design(按分类浏览文章的页面),显然最后会变成http://press.coolcfan.org/design,这肯定也不对……

实在是很难解决了~~

ICEST
那就复杂了,得写好几条,把那几个情况排除就好了,也不复杂,但是毕竟是几条规则了,以后再有变就越来越乱了

coolcfan
综上所述,就是除了之前永久链接的结构转向之外,别的都不转向
能不能这样想:

http://press.coolcfan.org/notes/design/from-chars-to-logo-chapter-three/

现在的地址都是这个结构,那么寻找notes/design/这样的组合,并且前后都还有字符的情况,然后将其干掉,而不是去排除一大堆东西?

ICEST
都是notes/design ?

coolcfan
呃……

ICEST
那好办啊

coolcfan
不只是那个

ICEST

coolcfan
但是我的分类数量有限啊
比起一时半会儿找不全的排除项
可能的分类链接结构倒是一下子都能找全嘛

ICEST
嗯,这样会比刚才排除简单些

coolcfan
而且这样的话只需要写一条,剩下的就都是机械的修改
这个匹配应该比较简单吧,注意notes/design/前后都得有字符就行了

ICEST
嗯,简单的

跑题了一会儿……继续

coolcfan
来来来
能把刚才我说的那个匹配写一下正则么
就写匹配notes/design/这种情况的吧

ICEST

RewriteRule ^notes/design/([^/]+)$ /$1 [R=301,L]

类似这样写吧

coolcfan
RewriteRule ^notes/design/([^/]+)$ /$1 [R=301,L],加完我就500了

ICEST
呵呵,是有问题
昨天的删掉,只用这一句

coolcfan
似乎不行

ICEST
呵呵,不懂了,你加在前面还是后面的

coolcfan
所有的子链接都打不开的说

ICEST
我直接去看看吧

coolcfan
我把根目录的.htaccess下载回来,加了这句,然后传到press目录的,根目录的是空的……
后台倒是一点儿事儿都没有~~

ICEST
wp的保留

coolcfan
囧一个
你有原版不,丢一个过来,这儿都覆盖了

ICEST

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

coolcfan
然后你写的那个应该加在哪

ICEST
RewriteBase /后面

coolcfan
ok

ICEST
再加个NC
RewriteRule ^notes/design/([^/]+)$ /$1 [R=301,L,NC]

coolcfan
cool啊! 等回去再把这个整理出一篇日志来

ICEST
嗯,好的

coolcfan
写全了就是这些???

RewriteRule ^ishow/projects/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^ishow/life/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^ishow/think/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^ishow/works/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^love/book/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^love/music/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^love/website/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^love/pictures/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^love/soft/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^notes/wordpress/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^notes/flash/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^notes/web/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^notes/misc/([^/]+)$ /$1 [R=301,L,NC]
RewriteRule ^notes/design/([^/]+)$ /$1 [R=301,L,NC]

ICEST
嗯,呵呵,一排子,但还算简单

coolcfan
我试试~每一条都要加L和NC么

ICEST

coolcfan
可是现在怎么不转向呢

ICEST
那你一条条加啊,应该没问题的啊

coolcfan
你看看,应该都转到404页 才对啊

ICEST
怎么会是404呢

coolcfan
因为我还没改永久链接结构啊

ICEST

coolcfan
比如访问http://press.coolcfan.org/ishow/projects/chandler-small-logos
应该转到http://press.coolcfan.org/chandler-small-logos
我还没改成这样,所以会WP会显示404页

ICEST
你又删掉了?

coolcfan
等下
刚才似乎被WP重置了一下

ICEST
哦,wp会改掉啊,那不爽了

coolcfan
修改永久链接结构时好像会重写.htaccess来着……
汗一个……

ICEST
2个办法,写在wp那块.htaccess外面,或者在wp里面设置刚才的规则

coolcfan
写在外面?

ICEST
不大好写啊
这些应该写前面,这样的话,要声明2次:
RewriteEngine On
RewriteBase /

coolcfan
没事儿

ICEST
在前面写

coolcfan
只要我不再改永久链接结构就行了呗

ICEST
RewriteEngine On
RewriteBase /
你的规则
# BEGIN WordPress

coolcfan
我试试

ICEST
不知道声明2次行不行的,应该没事

coolcfan
有效

ICEST

coolcfan
诶? 这都能转过去啊:

http://press.coolcfan.org/ishow/update-paused-for-maintenance

转成http://press.coolcfan.org/update-paused-for-maintenance了

ICEST
不应该啊

coolcfan
事实是竟然转过去了……汗……

ICEST
难道wp自身也就帮忙转?你现在去掉刚才写的,试试这个地址会不会转

coolcfan
怪了,一级分类的,WP自动给转了

ICEST
应该是wp转的

coolcfan
二级分类的,则不会转,必须要写.htaccess才行
就是说分类有两层的,WP不会自动转向

ICEST
搞不懂,这个wp也很难处理好

coolcfan
怪了哈
WP为啥会自动给转向呢

ICEST
不怪,怪的是只能转1层

……………………

以上就是我和ICEST的聊天记录,总结一下:

1、如果排除起来很麻烦,不妨从正面入手;
2、修改WP的永久链接结构,WP会把位于# BEGIN Wordpress和# END Wordpress之间的内容重置,所以把自己的写在外面,或者先改完永久链接结构,再上传;
3、Wordpress可以自己搞定只有一层分类的永久链接,但是无法搞定二层或更多的——如果你硬要用Wordpress的转向,那就用Redirection这个插件吧。
4、能用.htaccess就别用Wordpress,后者转向时要多运行一次WP的PHP程序,效率不及前者(毕竟前者是Apache直接转的)


相关日志