这个Wordpress插件可以统计Feed的订阅者,并可以生成类似于FeedBurner那样的条形统计图。 有如下的一些特点:
- 可以输出FeedBurner样式的统计图;
- 支持在线、离线阅读器的统计;
- 可以自定义各种阅读器的UserAgent标识,自行判断某个UserAgent是否为合法的阅读器;
- 可以生成FeedBurner样式的订阅者数图片。

安装方法
首先说明,这个插件仅适用于那些没有使用FeedBurner、FeedSky烧制feed的blogger们。 如果你使用了这些烧制服务,该插件将无法统计到烧制后feed的订阅数。
Windows下的安装方法很简单,解压插件到plugins目录下,在控制台中启动插件即可。 Linux下安装方法略为复杂,因为涉及到目录权限的问题,需要一些简单的Linux知识。
另外,本插件由于需要自己定义阅读器的标识符,所以最初安装时无法识别任何阅读器。 为解决这个问题,我在附件中放了一些阅读器的标识符数据,这是我一个月以来积累下的数据, 虽不敢保证很全面,但一般常见的浏览器都在里面。安装插件之后将其导入到数据库中即可。
下面是完整的安装方法:
- 解压缩插件到 wp-content/plugins 目录下;
- 进入Wordpress管理界面,在“插件”中找到“My Feed Stats”插件,启用;
- 利用phpMyAdmin等工具导入插件附带的 mfs_readers.sql。(如果你修改了wordpress的表前缀,请打开mfs_readers.sql并自行修改其中的表名。)
- 进入“管理->Feed统计”,设置订阅者图片的路径、颜色和显示的文字。这里图片路径是相对于wordpress根目录的路径,比如设置路径为 a/feeds.png,实际的图片URL就是
; - 如果操作系统是Linux,请设置插件目录下的 feeds-sample.png 的权限为 777,并利用touch命令手工创建上一条订阅者图片的文件(空文件即可),设置权限为777。
- 等待一天之后看统计结果吧!
关于版权
本插件的版权遵循GPL,请阅读插件内附带的license.txt文件。
本插件使用的字体文件 terminal6-modified.gdf 来源于 http://www.widgnet.com/gdf_fonts 。
下载地址
更新
2007/11/15,版本1.0.1:修改插件安装之后feed访问出错的一个bug。
其实做一个像feedburner和feedsky那样的feed统计功能并不难——如果你只是想自己用的话。
做feed统计需要实现的几个功能:
- 收集user-agent
- 分析近期的user-agent数据并统计每种阅读器的数目
- 定义常见阅读器的标记
- 绘制图表
而在实际操作中需要注意,统计user-agent时要排除掉浏览器、spider、bot等,仅统计阅读器的数字。而阅读器则分为在线阅读器和离线阅读器两种,在线阅读器一般都会通过user-agent报告订阅者数量(40 subscribers),而离线阅读器则不会。因此在线阅读器仅需要根据报告的数字统计订阅者即可,而离线阅读器则要根据IP地址来统计订阅者。
那么如何安装到wordpress里面?在init action上挂个钩子,判断一下request_uri是不是feed就行了。
最后,这个方法会跟wp-cache插件冲突,因为wp-cache会cache feed,一旦cache之后init action就不动了,所以要注意设置wp-cache使其不cache feed才行。
半个月前将永久链接的格式从 /archives/%post_id%.html 修改成了 /%year%/%monthnum%/%day%/%postname%/,结果日IP由原来的100多降低到现在的不到30。可能是永久链接的更改影响了Google的收录吧。幸亏fcicq的提醒,我装上了Permalinks Migration Plugin这个插件。这个插件可以识别旧的永久链接格式,然后通过301重定向将它转到现在的永久链接上,这样就不会影响搜索引擎收录了。
这个插件据说是个中国人写的。插件很小,仅一个文件,激活之后在选项中出现一个PermalinksMigration的选项,在其中填入旧永久链接的格式即可完成重定向。
前两天在smalldust的blog上看到了关于扑克牌验证码 的想法。觉得这个想法甚是有趣。 想起了以前在一个网站看到一个猫验证码的想法,基本上就是随机出九张图片, 让评论者选出哪几张图是猫,以此来防止垃圾评论。 而smalldust的扑克牌验证码则是一个更有趣的主意。
与smalldust交涉之后做了这个插件,可以在评论页面上显示扑克牌验证码。 版权采用GPL。截图如下:

另外,我的空间因为有广告,无法使用这个有趣的插件了,遗憾啊。
Wordpress的官方文档对数据库的结构描述得并不充分,索性自己来分析一下。首先从整体结构入手。 下面是2.0.5版的数据库结构图(E-R图)。为了节约篇幅,这里仅列出了主键和外键。 图中菱形表示1:n的关系,白色部分为1,黑色部分为n。

Wordpress共有10个表,按照功能大致分为四类。
- user: 用户信息,包括wp_users表和wp_usermeta表。
- post: 文章及评论信息,包括wp_posts、wp_postmeta、wp_comments、wp_post2cat以及wp_categories五个表。
- link: 链接信息,包括wp_links表和wp_linkcategories表。
- option: 全局设置信息,包括wp_options表。
个人认为这个数据库有两个冗余的地方。一个是wp_post2cat表中的主键rel_id,其实可以不要rel_id,而使用post_id和category_id两列作为主键; 另一个是wp_options表,option_id列为自动增长列,仅使用该列即可作为主键,而不需要option_id、blog_id、option_name三列联合做主键。
另外,表的命名规则也很有意思。基本规则总结如下:
- 保存对象的基本属性,命名为 wp_objects,使用复数(如 wp_posts,wp_comments);
- 保存对象的扩展属性,命名为 wp_objectmeta,使用单数(如wp_postmeta,wp_usermeta);
- 多对多关系,命名为 wp_a2b,其中a和b分别为多对多关系两端的对象名的缩写(如wp_post2cat)。
Wordpress的效率问题似乎一直是议论的热点,今天来看看其中一条SQL语句的效率。
首先将所有插件禁用,并切换为默认模板。 然后按照《WordPress执行效率问题》这篇文章的方法, 在 wp-config.php 中加入
<?php define('SAVEQUERIES', true); ?>
在模板的 footer.php 中加入
<!-- <?php var_dump($wpdb->queries); ?> -->
访问首页,即可从源代码中看到SQL语句。
执行时间最长的是这一条,花了0.02秒:
SELECT DISTINCT * FROM wp_posts
WHERE 1=1
AND post_date_gmt <= '2007-01-02 07:12:59'
AND (
post_status = 'publish'
OR
post_author = 1
AND post_status != 'draft'
AND post_status != 'static'
)
AND post_status != 'attachment'
GROUP BY wp_posts.ID
ORDER BY post_date DESC
LIMIT 0, 10"
这条语句位于 class.php 的 WP_Query->&get_posts() 函数。
说说这个SQL语句的问题。不妨先来看看 wp_posts 表的结构(省略无关列)。
| 列名 | 类型 | 索引 |
| ID | bigint(20) | PRIMARY |
| post_author | bigint(20) | |
| post_date_gmt | datetime | |
| post_status | enum | INDEX |
| post_name | varchar(200) | INDEX |
首先是关键字 DISTINCT,DISTINCT的作用是去掉重复的数据, 相当于对选择的列进行 GROUP BY。而这条语句中选择了 * 列,包含了主键列 ID, 每行数据必然不相同,因此 DISTINCT 关键字起不到任何作用, 白白浪费一次排序。
其次是 post_date_gmt 和 post_author 上的比较操作。wp_posts表仅有 ID、post_status 和 post_name 列上有索引,对其他列的比较操作使得mysql不得不访问wp_posts表的所有数据, 影响效率。
然后是 post_status 上的不等于的比较。对索引列使用不等于比较, 会导致数据库不能使用索引(索引只能判断等于关系)。 另外显然已经有了 post_status = 'publish' 的条件, 不必再判断 post_status != 'attachment'。
最后是 GROUP BY wp_posts.ID,仍然是对一个不会重复的列进行 GROUP BY, 毫无意义。
如果不考虑功能损失,将这个 SQL 语句优化为下面这样,则仅需花费0.003秒。
SELECT * FROM wp_posts WHERE 1=1 AND post_status = 'publish' ORDER BY post_date DESC LIMIT 0, 10"
使用Apache Bench做测试,优化前平均每个请求的处理时间为 503.125ms,优化后为 478.125ms。
Wordpress的表名前缀默认为 wp_,该值为Wordpress安装时指定,安装之后无法更改。但若不得已需要改变时,可以使用以下方法。
- 将数据库导出。
- 将表中的所有 `wp_ 替换为 `wp2_,其中 wp2_ 为新的表前缀。
- 导入数据库。
- 修改 wp2_options 表的数据,在第四行左右有个 wp_user_roles,将其修改为 wp2_user_roles。
- 修改 wp2_usermeta 表的数据,将所有的 wp_user_level 修改为 wp2_user_level,所有的 wp_capabilities 修改为 wp2_capabilities。
如果忘记修改 wp2_options 和 wp2_usermeta 中的值,后台管理就无法使用。
这个话题似乎是老调重弹了,也有很多人给出了相应的方法。我的方法如下:
RewriteCond %{REQUEST_URI} !^/wp-includes/images/noimage.png$ [NC]
RewriteCond %{HTTP_REFERER} !^http://[0-9a-z]+\.inspiremedia\.org/.*$ [NC]
RewriteRule \.(jpg|gif|png|zip|gz|rar)$ http://tech.inspiremedia.org/wp-includes/images/noimage.png [R,L]
主要功能位于第二行,当请求的HTTP_REFERER头不输入本站所在的域时,则执行第三行的重写规则,重定向至 noimage.png。 第二行最后的[NC]表示匹配时忽略大小写。第一行用于防止死循环。
2006-12-26
接受建议,将重写规则仅适用于 wp-content/uploads 下的文件。
RewriteCond %{HTTP_REFERER} !^http://[0-9a-z]+\.inspiremedia\.org/.*$ [NC]
RewriteRule wp-content/uploads/.*\.(jpg|gif|png|zip|gz|rar)$ http://tech.inspiremedia.org/wp-includes/images/noimage.png [R,L]
这是一个根据IP地址判断所在国家的插件。用处很多,显示评论者国家、阻挡垃圾评论等等。 其实这种插件有很多,比如IP to Country, 不过这个程序感觉一来效率不高,二来用起来也不是很方便。于是我写了这个插件,仅仅一个函数。
原理很简单,将IP地址范围保存到MySQL数据库中,然后通过SQL取出给定IP地址的数据,显示国家即可。
$ip = ip2long($ipaddr);
$sql = sprintf("SELECT country FROM ip2country WHERE ip_from<=%u AND ip_to>=%u", $ip, $ip);
$row = $wpdb->get_row("$sql");
return $row->country;
阅读全文 »在blog上添加mp3播放器的方法有很多,这里介绍通过 Flash MP3 Player 来播放音乐的方法。
首先到 Flash MP3 Player 的主页上下载该程序。 解压缩之后,将 mp3player.swf 和 ufo.js 两个文件放到服务器上,这里假设放在 /musicplayer 下。 (注意,Flash MP3 Player有个bug,路径名中不能包含 mp3 字样,否则不能正常读取播放列表。)
在wordpress当前主题目录中建立 mp3player.php,内容如下。
<p id="mp3player"><a href="http://www.macromedia.com/go/getflashplayer" target="_blank">下载 Flash Player</a>来播放音乐。</p>
<script type="text/javascript">
var FU = {
movie:"/musicplayer/mp3player.swf",
width:"190",
height:"20",
majorversion:"7",
build:"0",
bgcolor:"#FFFFFF",
flashvars:"file=/musicplayer/playlist.xml&showdigits=true&repeat=true&shuffle=false&lightcolor=0x0080FF&backcolor=0x0066AA&frontcolor=0xEEEEEE" };
};
UFO.create( FU, "mp3player");
</script>
然后在 sidebar.php 的适当位置加入:
<?php include(TEMPLATEPATH . '/mp3player.php'); ?>
在 header.php 中加入:
<script type="text/javascript" src="/musicplayer/ufo.js"></script>
最后将mp3文件上传到 /musicplayer 目录下,最好文件名为英文名,然后在 /musicplayer 下建立 playlist.xml 文件。
<?xml version="1.0"?>
<playlist version="1" xmlns="http://xspf.org/ns/0/">
<trackList>
<track>
<title>Music Title</title>
<creator>Singer</creator>
<location>/musicplayer/song.mp3</location>
</track>
</trackList>
</playlist>
效果如下图。
