JWPL(Java Wikipedia Library)是一个开源的访问wikipeida数据的java api包。
项目主页:http://code.google.com/p/jwpl/
它的核心功能包括
1. 快速有效的访问wikipeia数据
2. 分析处理wiki格式数据
3. 可以处理任何语言
除了这些核心和基础的功能外,JWPL有一套处理wikipeida的编辑历史记录数据的版本再现工具。
这些版本再现工具有以下功能
1. 重新生成某个历史时刻的wikipeida数据(TimeMachine)
2. 访问wikipeida所有的版本信息(RevisionMachine)
3. Dedicated revision storage format
下面访问wikipedia数据的实例代码:
示例代码1:显示页面信息
// 数据库连接参数配置
DatabaseConfiguration dbConfig = new DatabaseConfiguration();
dbConfig.setHost("SERVER_URL");
dbConfig.setDatabase("DATABASE");
dbConfig.setUser("USER");
dbConfig.setPassword("PASSWORD");
dbConfig.setLanguage(Language.english);
// 创建Wikipedia处理对象
Wikipedia wiki = new Wikipedia(dbConfig);
String title = "Hello world";
Page page = wiki.getPage(title);
// wikipedia页面的title
System.out.println("Queried string : " + title);
System.out.println("Title : " + page.getTitle());
// 是否是消歧页面
System.out.println("IsDisambiguationPage : " + page.isDisambiguation());
// 是否是重定向页面
System.out.println("redirect page query : " + page.isRedirect());
// 有多少个页面指向该页面
System.out.println("# of ingoing links : " + page.getNumberOfInlinks());
// 该页面指向了多少个页面
System.out.println("# of outgoing links : " + page.getNumberOfOutlinks());
// 该页面属于多少个类别
System.out.println("# of categories : " + page.getNumberOfCategories());
StringBuilder sb = new StringBuilder();
// 页面的所有重定向页面
sb.append("Redirects" + LF);
for (String redirect : page.getRedirects()) {
sb.append(" " + new Title(redirect).getPlainTitle() + LF);
}
sb.append(LF);
// 页面的所述的所有类别
sb.append("Categories" + LF);
for (Category category : page.getCategories()) {
sb.append(" " + category.getTitle() + LF);
}
sb.append(LF);
// 指向该页面的所有页面
sb.append("In-Links" + LF);
for (Page inLinkPage : page.getInlinks()) {
sb.append(" " + inLinkPage.getTitle() + LF);
}
sb.append(LF);
// 该页面指向的所有页面
sb.append("Out-Links" + LF);
for (Page outLinkPage : page.getOutlinks()) {
sb.append(" " + outLinkPage.getTitle() + LF);
}
System.out.println(sb);
示例代码2:显示类别信息
// 数据库连接参数配置
DatabaseConfiguration dbConfig = new DatabaseConfiguration();
dbConfig.setHost("SERVER_URL");
dbConfig.setDatabase("DATABASE");
dbConfig.setUser("USER");
dbConfig.setPassword("PASSWORD");
dbConfig.setLanguage(Language.english);
// 创建Wikipedia处理对象
Wikipedia wiki = new Wikipedia(dbConfig);
String title = "Towns in Germany";
// 创建类对象
Category cat = wiki.getCategory(title);
StringBuilder sb = new StringBuilder();
// 类别名
sb.append("Title : " + cat.getTitle() + LF);
sb.append(LF);
// 类别的父类信息
sb.append("# super categories : " + cat.getParents().size() + LF);
for (Category parent : cat.getParents()) {
sb.append(" " + parent.getTitle() + LF);
}
sb.append(LF);
// 类别的子类信息
sb.append("# sub categories : " + cat.getChildren().size() + LF);
for (Category child : cat.getChildren()) {
sb.append(" " + child.getTitle() + LF);
}
sb.append(LF);
// 类别下的所有页面
sb.append("# pages : " + cat.getArticles().size() + LF);
for (Page page : cat.getArticles()) {
sb.append(" " + page.getTitle() + LF);
}
System.out.println(sb);
这里主要介绍如何搭建起使用JWPL那几个功能核心的平台,不包括后面利用版本数据的那几个工具。
JWP核心API访问的数据都是存储在mysql数据库中结构化的数据。所以,重点就是要怎么样把最原始的wikipeida dump数据转换成mysql数据库的记录格式,并导入mysql中,主要利用的就是JWPL提供的数据转换工具---DataMachine。
另外,本文最后还介绍了下转换后mysql数据库中各个表的结构,相信了解了这些表结构会对阅读API有很大帮助。
1. wikipeida数据准备:从 dump处下载需要的数据,选择语言[LANGCODE]和dump日期[DATE]: http://dumps.wikimedia.org/
最起码要下载下面三个文件:
[LANGCODE]wiki-[DATE]-pages-articles.xml.bz2
[LANGCODE]wiki-[DATE]-pagelinks.sql.gz
[LANGCODE]wiki-[DATE]-categorylinks.sql.gz
把该文件放入一个目录中,比如~/en2012
2. 下载JWPL DataMachine jar包:为了避免包引用引起的不必要麻烦,建议给我一样,直接去maven库中下载整个jar-with-dependencies.jar
下载地址是:http://search.maven.org/#search|ga|1|tudarmstadt.ukp
找出de.tudarmstadt.ukp.wikipedia.datamachine对应的 jar-with-dependencies.jar 文件
3. 运行DataMachine
命令:java -cp jar-with-dependencies.jar de.tudarmstadt.ukp.wikipedia.datamachine.domain.JWPLDataMachine [LANGUAGE] [MAIN_CATEGORY_NAME] [DISAMBIGUATION_CATEGORY_NAME] [SOURCE_DIRECTORY]
其中:
LANGUAGE - 从这里可以查看到jwpl支持的语言,选择一个你下载的wikipedia语言,比如english
MAIN_CATEGORY_NAME - 填写一个Wikipedia类别层次上属于顶层的类别,比如:Contents
DISAMBIGUATION_CATEGORY_NAME - 填写一个有消歧类别的类别名,比如:Disambiguation_pages
SOURCE_DIRECTORY - 上面三个wikipedia文件的目录,比如: ~/en2012
比如:
java -Xmx2g -cp jar-with-dependencies.jar de.tudarmstadt.ukp.wikipedia.datamachine.domain.JWPLDataMachine english Contents Disambiguation_pages ~/en2012
注意: 如果你的dump文件很大,发现上例中给JVM分别2G内存不够用,可能你就需要多分配写内存给JVM了,比如4G, "-Xmx4g"
注意: 如果你的系统默认编码不是utf-8(比如windows), 可能需要再加一个参数:-Dfile.encoding=utf8 flag.
4. DataMachine需要运行很长时间,我的笔记本大概运行了一整天。运行完会在SOURCE_DIRECTORY目录下生成一个output目录,该目录里面有11个文件,这11个文件就是需要导入到mysql中的结构化数据了。
注意:SOURCE_DIRECTORY 下还会产生一些.bin文件,这些都是临时文件,程序运行完就可以把他们删除了。
5. 创建mysql数据库及表结构
创建数据库命令(数据库名DB_NAME可以自行设定):
CREATE DATABASE [DB_NAME] DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
从这里下载查看创建所有表结构的mysql脚本,比如:
--
-- Table structure for table `Category`
--
DROP TABLE IF EXISTS `Category`;
CREATE TABLE `Category` (
`id` bigint(20) NOT NULL auto_increment,
`pageId` int(11) default NULL,
`name` varchar(255) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `pageId` (`pageId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
注意:为了省去不必要的麻烦,最好使用5.0以上版本的mysql。如果你的版本是4.*或者更早的,看这个指导文档
注意:需要保证创建的数据库的编码是utf-8
6. 导入output目录下的文件数据到mysql数据库中:
mysqlimport -uUSER -p --local --default-character-set=utf8 [DB_NAME] `pwd`~/en2012/output/*.txt
注意:如果导入出现问题,因为有些环境可能不支持通配符批量导入,那就去网上搜索下如何导数据到mysql中。
大功告成,你可以使用最最上面的一些例子去访问wikipeida的数据了。
推荐使用Navicat客户端程序访问mysql数据库,去官网直接下载Premium版本。当然,如果你需要注册码或者破解,像我这种知识产权绝对拥护者是不会告诉你网上可以搜索到最新版的注册码的。
对应那11个txt文件,数据库中包含11个表。
其实从表名大概就都能知道各个表存储的是什么信息了。
各个表结构:
category --> 类别信息
pageId:类别ID,唯一
name:类别名
category_inlinks --> 指向类别的链接信息
id:类别ID,不唯一
inLinks:该类别父类ID,也就是指向该类别的类别ID
category_outlinks --> 类别指向的链接信息
id:类别ID,不唯一
outLinks:该类别子类ID,也就是该类别指向的那些类别的ID
category_pages --> 页面与类别的关系表
id:类别ID,不唯一
pages:属于该类别ID的页面ID
metadata --> 该wikipedia的一些元信息,只有一条记录
language:语言
disambiguationCategory:运行DataMachine填写的消歧类别
mainCategory:运行DataMachine填写的顶层类别
nrofPages:页面个数
nrofRedirects:重定向个数
nrofDisambiguationPages:消歧页面个数
nrofCategories:类别个数
version
page --> 页面信息
pageId:页面ID
name:名字
text:全文,包含wikimeida的标记信息
isDisambiguation:是否是消岐页面
page_categories --> 页面与类别的关系表与category_pages信息重复
page_inlinks --> 指向页面的页面信息
id:页面ID,不唯一
inLinks:指向该页面ID的页面ID
page_outlinks
id:页面ID,不唯一
outlinks:该页面ID指向的页面ID
page_redirects
id:页面ID,不唯一
redirects:重定向到该页面ID的所有页面ID
pagemapline --> 所有页面的title信息,处理重定向等有用处
id:该页面ID
name:页面title名字
pageID:页面ID,如果该页面是重定向页面,该pageID是其指向的那个包含信息的页面ID
stem:***暂无信息
lemma:***暂无信息
相信这样的数据就可以满足大部分NLP&IR工作者的需求了。
个人的下一步工作:
1. 学习了解此处用到的OR MAPPING工具Hibernate;
2. 更重要的是阅读DataMichine的代码和了解其实现原理;