Ling Zhang Ling Zhang's Blog

博客网(bokee/blogchina)至WordPress搬家攻略

摘要

Web内容集成曾经是最困难的工作之一,感谢XML/Web services,在Web 2.0的时代终于可以比较容易的实现了。目前绝大部分blog系统都支持两种方式的内容输入:标准的基于Web的方式,即用户登录、发贴;另外就是通过API利用客户端软件发贴。这两种方式可以简单的想象成WebMail和基于SMTP邮件客户端。本文实现了基于半结构化内容抽取和异构XML目标数据的集成。

实现方法

现在常用的Blog API有Blogger API, MetaWeblog API, Movable Type API等,这些API都采用了XML-RPC进行数据包装和传输。 blogchina.com目前仅支持早期的Blogger API 1.0(而且是部分支持),而WP同时支持这三种API。

为了把http://zhangling.blogchina.com 里过去两年的文章完整的搬到新系统中,我首先尝试了用Blogger API去读取blogchina里的文章,但碰到了问题。

用Java开发,我用了Apache的XML-RPC包。经尝试,发现blogchina仅支持blogger.getUserInfoblogger.getTemplateblogger.getUsersBlogs等几个有限的方法,对于关键的抽取文章内容的函数则完全不支持。这意味着所有的内容无法通过编程的方法获得,工作量一下上升了很多。

于是我在浏览器分别打开04-06年的文章列表,用下载工具将页面里所有博客文章进行批量下载(还好这个过程的工作量不是很大),然后在本地磁盘上根据年份和文章分类建立多层子目录,把对应的文章放在不同目录下面。现在的问题变成如何从HTML页面中把文章标题、内容、发贴日期和评论分别抽取出来作为XML-RPC参数发送给WP系统自动建立新文章。仔细研究了这些HTML文件,发现它们都具有相同的结构和布局,仅仅是内容上的变化,其他如布局和风格几乎完全一样。接下来就需要分析HTML代码找到文章标题、内容、日期、评论部分的特征标签以进行内容抽取。比如就标题来讲,所有的标题前都有”diaryTitle"标签;所有发贴日期都符合正则表达式"年\\S*月\\S*日.*星期\\S\\s\\d\\d:\\d\\d",等等这些信息都对内容的正确提取提供了保证。

根据分析得到的特征标签,写了4个Java class(TitleExtractor, ContentExtractor, DateExtractor和CommentExtractor) 。对300多篇文章进行测试,抽取成功率100%(当然还写了一些字符串处理函数解决一些有变数的字串)。于是,数据源的问题得到的解决。

花费最多时间的倒是对WP的数据写入部分。我用了MetaWeblogAPI,使用XML-RPC中的XmlRpcClient类,构建好参数列表,测试发现中文出现问题。Java程序送出的XML数据包在WP系统上显示为乱码。经调试确认XML-RPC使用的是UTF-8编码,而WP也是配置成UTF-8。在调试多次失败后,我用Ethereal(已经改名成WireShark)捕获了发出去的HTTP数据包,发现Apache的XML-RPC实现把中文字符进行HTML转义,导致WP无法识别。为了验证,我装了Zoundry并尝试发贴,在捕获的HTTP请求包中,Zoundry把“中文标题”四个汉字编码成“\344\270\255\346\226\207\346\240\207\351\242\230”,而且WP正确的接受并成功显示!接下来,我下载了Apache commons codec包,尝试了里面多个编码器,始终没能成功,不得不考虑使用其他Java实现。

最终我找到了合适的包Redstone XML-RPC,它顺利的把我GB2312编码的文章上传到WP上(需要把WP缺省编码改成GB2312),于是剩下的事情就是一个for循环对目录里的所有文件做一次内容提取、参数组装和网络调用。为了简单,我把评论部分附加在正文末尾(因此可以在新博客老帖子的正文部分里看到很多老系统的影子,如黑色的头像:)

结论

虽然一些商业系统开始提供博客搬家服务(如blogbus和讯),由于可用性的限制要实现完整的系统搬家难度还是非常大(我在blogbus尝试10篇文章的搬家未获得成功)。因此,如果懂软件开发的话,自己写点搬家程序会更容易、更便捷。

参考文献

1. Apache XML-RPC: http://ws.apache.org/xmlrpc/
2. WordPress API: http://codex.wordpress.org/XML-RPC_Support
3. Ethereal Bug 894: http://bugs.ethereal.com/bugzilla/show_bug.cgi?id=894
4. PHP和JAVA的XML-RPC中文问题解决办法: http://fanqiang.chinaunix.net/program/php/2005-09-06/3586.shtml

附录(部分代码)

XmlRpcClient client = null;
try {
client = new XmlRpcClient(new URL("http://www.zhangling.org/blog/xmlrpc.php"), true);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

for (int i = 0; i < files.length; i++) {
try {
filename = folder.getAbsoluteFile() + "\\" + files[i];
FileInputStream fileInput = new FileInputStream(filename);
InputStreamReader reader = new InputStreamReader(fileInput,"GB2312");
BufferedReader bufferReader = new BufferedReader(reader);
while (bufferReader.ready()) {
content = content + bufferReader.readLine() + "\n";
}
} catch (Exception e) {
System.err.println(e);
}

title = titleExtractor.getTitle(content);
description = contentExtractor.getContent(content)
+ commentExtractor.getComment(content);
datestring = dateExtractor.getDate(content);
content = "";

Vector v = new Vector();
v.add("1");
v.add("AAAA");
v.add("********");
Hashtable hashtable = new Hashtable();
hashtable.put("title", title);
hashtable.put("description", description);
Date date = new Date(datestring);
hashtable.put("dateCreated", date);
String category[] = new String[1];
category[0] = "技术";
hashtable.put("categories", category);
v.add(hashtable);
v.add("true");
try {
Object result = client.invoke("metaWeblog.newPost", v);
System.out.println("received: " + result);
} catch (Exception e) {
Logger.writeLog(filename + ":" + e);
System.out.println(e);
}

}

}

Read more

本人新博客网站架构简介

本系统用的是dreamhost的虚拟主机服务(多谢丁峰推荐),20GB空间,支持FTP, Telnet, 可安装WordPress(当前我使用的blog系统)和其他PHP论坛等服务器端软件。服务费是一年90美元,用了网上贴的coupon code后实际第一年费用22美元。

zhangling.org是01年左右我在万网注册的,一直没怎么用,这次博客搬家派上了作用。只需要在万网的国际域名管理中把DNS服务器指向dreamhost的DNS就可以了。

现在的WordPress(WP)系统比博客网的blogdriver提升了一大步,好比Eclipse和Symantec VisualCafe的区别 。作为最流行的blog系统之一,WordPress有众多的插件(我安装了“流量统计”和“最新评论”插件。由于导致IE显示问题,“最新评论”插件尚未激活)和多种API支持。绝大多数blog client对WP都有很好的支持。

在稍微学习了WP的管理之后,更新了一些系统配置和部分页面模板;在sidebar增加了照片、日历、最新文章等内容。

</p>

Read more

博客网搬家动因

1. 博客网(bokee.com, blogchina.com)系统不稳定,经常出现无法发贴的情况。写评论会出现多次提交的相同评论内容。最近出现的无法回复英文字符的情况,让人无法接受;

2. 博客网不支持分类的RSS,一个博客只有一个总的RSS。因为需要向CSDN Blog导出部分分类,这直接导致更换系统;

3. 博客网登录后session有效期过短,稍微长一点的帖子需要不停备份到临时打开的notepad里以免丢失;

4. 缺乏内容管理功能。内容易进不易出,提供对外的编程接口极有限。

Read more

博客搬家成功

自己写了程序,把博客网上(http://zhangling.bokee.com)三百多篇文章搬到了本网站上,老贴的标题、内容、时间、评论和贴图都完整的保存下来。

写Java搬家程序花了1天半,最终的乾坤大挪移花了10分钟。

稍后介绍一下博客搬家的实现方法和技术细节。

</p>

Read more

毛新生在CSDN上SOA访谈

毛新生是我们CDL(中国软件开发中心)SOA设计中心主任,IBM中国本土成长起来的第一位STSM (Senior Technical Staff Member)。我和新生有过不多的聊天,他是一个真正的thinker,视野广阔,思维活跃。

这里是毛新生的博客:http://mxs.blog.ccidnet.com

还有这段CSDN的SOA访谈录像:mms://61.186.252.133/CSDN_Live_13/CSDN_Live_13_A.wmv

Read more

今天我休息

今天休假一天。

早上4号线转26路去上海图书馆看书。在3楼外文期刊阅览室翻出了过去几个月的技术类期刊,还有一些网络休闲类读物。我在3月份英国出版的.NET杂志上看到了国产“后舍男孩”的网络截屏,还有Moto请他们为手机宣传的报道,文中还提到了那个在打CS的背影。

从上图出来去了著名的DZMZ(大自鸣钟),这是坊间流传的上海淘碟圣地。关于大自鸣钟的位置,网上有不少指示,就是靠近长寿路,西康路,宜昌路,还靠近轻轨的一个破旧的大楼里。经过实地勘查,确定大自鸣钟的物理位置是:(31°14'48.86"N 121°25'45.25"E)。请淘碟者自己mark吧。今天DZMZ场子里没什么人气,完全没有想象中的热烈,甚至不如蓝村路西段,比较失望的说。可能是因为没到双休日,不过摊子上中年妇女的一句话让我确信这里的确有一定权威性 - “问:某某碟有吗?答:网上碟报出了,但还没到”。

该去照二代身份证照片了。

</p>

Read more

关于评论无法输入英文的问题

刚才打了博客网的客服电话,说明了英文字符被过滤的问题(居然没人报过),客服人员自己试了一下,确实不能发英文。

等吧,从现在开始看多久能修好。

Read more

电台DJ的传值与传引用

105.7交通台晚上7点钟有档节目叫“淳子咖啡馆”,每期都有个主题,淳子在伤感怀旧一番后放一首歌,叙述一段后继续放歌。我平时能在下班的公交车上听完这个节目的上半部分。

今天晚上听歌的时候忽然想到一个技术问题:这些直播或者非直播的音乐节目中,往往要完整的播上几首歌曲,这些节目的录音资料是仅包含主持人说话的部分呢,还是连这些完整播放的歌曲一起被重新录制进去了。比如一个小时的“咖啡馆”,主持人说话的时间加起来可能只有20分钟,剩下40分钟全是歌曲,这个1小时的节目最后存档或者未来重播的时候是保存了完整的1小时资料,还是仅仅保存主持人的部分,在重新播放的时候由电台调度当场从曲库中找歌来播。

这是个有关存储空间与执行效率的问题,就是by reference和by value的区别。如果是by value,每首被播出的歌会无数次的被复制到各个音乐节目声音资料中,浪费了大量的存储资源(经典热门歌曲可能被复制到成百上千卷的磁带中);如果用by reference,虽然节省了存储空间,但在重播的时候需要有人在主持人话音结束的时候找到CD,定位track,再播放,太复杂了。不用说,电台一定用的是by value的做法,一来容量不是问题,二来资料的整理存档很容易。这好比做一个网页,要链接别人的一段内容,假如仅嵌入一个超链接的话,很难保证这个超链接未来还是否继续有效,与其这样不如copy & paste到自己的页面里,完全脱钩的自主管理和维护。

另外一个引起思考的问题是DJ们如何快速找到CD曲目(尤其是在直播节目中),电台内部是不是有一个可以直接供DJ使用的搜索引擎,根据歌手名、年代、曲名、歌词等搜索??我不知道。昨天中央5套“豪门盛宴”里张路介绍了一个点球技法 - “勺子球”,让我觉得更加有趣:体育部的人如何在这么短的时间内找到了这么多“勺子球”的录像(大概有10个左右),这些录像有的来自联赛,有的来自世界杯,而且不少都上了年头。这些视频资料在电视台是如何管理、分类、标签、检索的呢?可以想到的是给每场球赛加多角度的分类,然后加入一些tag,如“乌龙球”、“误判”等供方便日后检索,但像“勺子球”这样的关键词也会被资料管理员们tagging吗?我很怀疑,难道是全靠懂球的人回忆起来的,没太可能。。。。我猜Web 2.0这些东西,放到中央台估计会被仓库管理员鄙视的。。。

Ding Feng曾经研究过Dublin Core在图书馆学中的应用,现在看至少在视频的metadata标注上还是太粗粒度了。对于球赛来说,要不就把比赛解说词用语音识别转换成文字,然后把这些文字连同录像一起保存归档,文字部分供搜索之用(以后在引用06年意大利vs澳大利亚的录像资料时,只需要输入“灵魂附体”就可以了)。

Read more

餐馆点菜系统

晚上去蓝村路、东方路口新开张的可膳茶餐厅吃饭,结帐的时候瞅了眼小票,上面印着一个网址:http://www.canyin.com.cn。回家后登录网站,原来是家叫“世纪领航”的公司,专门提供餐饮专用软、硬件解决方案。以前在北京出差的时候就看到很多馆子用了无线的点菜PDA,上海却很少见到。

“世纪领航”把一些软件放到网上下载,我下载了其中一个压缩包,里面有叫"Mdac_.."的文件,应该是用了微软的数据访问组件。

绑定硬件来销售软件在中国是条不错的出路,虽然严格来将在餐饮领域这两者绑定的并不紧,不过餐厅老板为了完整可靠的解决方案,没什么必要去hack这些PDA搞盗版软件。

“世纪领航”是很好的国内行业软件(我宁愿称它是软件公司)的样本,不盲目玩高科技,抓行业、抓业务,垂直领域内做的风风火火的。

Read more