使用JWPL工具操作wikipedia数据

来源:互联网 发布:java for循环 小数点 编辑:程序博客网 时间:2024/06/05 06:37
来源:http://www.cnblogs.com/heshizhu/archive/2012/06/26/2564267.html


注,红色为我添加的说明

配置完把数据导入数据库了,后面使用JWPL库连接数据库还存在一些问题,其实不太好弄,我是用了其他人配好的包

【 把数据导入数据库后,需要连接数据库来做运算处理,这时候还需要另一个依赖包:de.tudarmstadt.ukp.wikipedia.api

下载地址是:http://search.maven.org/#search|ga|1|tudarmstadt.ukp

找出de.tudarmstadt.ukp.wikipedia.api对应的 jar-with-dependencies.jar 文件

注意,这个de.tudarmstadt.ukp.wikipedia.api包和下面的de.tudarmstadt.ukp.wikipedia.datamachine包不一样,后者是提取wikipedia数据的包,前者是操作数据库的包。

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数据的实例代码:

数据库连接参数配置的四个参数例子如下:

dbConfig.setHost("localhost");

dbConfig.setDatabase("wikipedia2013");

dbConfig.setUser("username");

dbConfig.setPassword("password");

这里localhost表示代码运行和数据库在同一台机器上,如果数据库和代码执行不在同一台机器,localhost为数据库所在机器的IP地址,注意,必须是代码运行机器可访问到的IP地址,例如同局域网“192.168.1.10”或者公网地址。wikipedia2013表示数据库名称。username和password是访问数据库wikipedia2013的用户名和密码。

示例代码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页面的titleSystem.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。

https://code.google.com/p/jwpl/wiki/DataMachine

另外,本文最后还介绍了下转换后mysql数据库中各个表的结构,相信了解了这些表结构会对阅读API有很大帮助。

1. wikipeida数据准备:从 dump处下载需要的数据,选择语言[LANGCODE]和dump日期[DATE]: http://dumps.wikimedia.org/

注:Wikipedia数据也可直接到Wikipedia的ftp下载,省去找数据麻烦:ftp://ftpmirror.your.org/pub/wikimedia/dumps/enwiki/,打开这地址后,选择你想要的版本,注意下载时,后面的名字要完全匹配,例如下pages-articles.xml.bz2时不要选择pages-articles-multistream.xml.bz2,因为按照本文方法不能解析multistream版本的

    最起码要下载下面三个文件:
        [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

按照上述的地址下下来的jar文件名称会比文章看到的长,没关系,只要把java命令行中的jar文件用完整的文件名表示即可,例如我下的最新版本是de.tudarmstadt.ukp.wikipedia.datamachine-0.9.2-jar-with-dependencies.jar,相应的命令行是:

java -Xmx2g  -cpde.tudarmstadt.ukp.wikipedia.datamachine-0.9.2-jar-with-dependencies.jar de.tudarmstadt.ukp.wikipedia.datamachine.domain.JWPLDataMachine english Contents Disambiguation_pages ~/en2012 

MAIN_CATEGORY_NAME和DISAMBIGUATION_CATEGORY_NAME可以在后面加en如果你用的是英文Wiki,例如Contents_en,Disambiguation_pages_en,不过使用了英文wiki后,用Contents和Contents_en是一样的效果

注意: 如果你的dump文件很大,发现上例中给JVM分别2G内存不够用,可能你就需要多分配写内存给JVM了,比如4G, "-Xmx4g" 
注意: 如果你的系统默认编码不是utf-8(比如windows), 可能需要再加一个参数:-Dfile.encoding=utf8 flag. 

例如:java -Xms2g -Xmx10g -Dfile.encoding=utf8  -cp de.tudarmstadt.ukp.wikipedia.datamachine-0.9.2-jar-with-dependencies.jarde.tudarmstadt.ukp.wikipedia.datamachine.domain.JWPLDataMachine english Contents Disambiguation_pages ~/en2012 

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;

为方便自动化,建议使用MySQL客户端例如SQLyog,用SQLyog连接并查看数据库。然后下载jwpl_tables.sql脚本,在表格创建之前创建数据库,即在jwpl_tables.sql里表格创建之前加入以下两条语句:

CREATE DATABASE [DB_NAME] DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

USE [DB_NAME];

然后在MySQL客户端SQLyog执行该sql文件,就创建了数据库和wikipedia相应的11个表格。

注意:为了省去不必要的麻烦,最好使用5.0以上版本的mysql。如果你的版本是4.*或者更早的,看这个指导文档

注意:需要保证创建的数据库的编码是utf-8

6. 导入output目录下的文件数据到mysql数据库中:

mysqlimport -uUSER -p --local --default-character-set=utf8 [DB_NAME] `pwd`~/en2012/output/*.txt

如果这语句报错,说没有[DB_NAME].'pwd'这表格,改成以下语句(去掉password选项)并按要求输入密码:

mysqlimport -uUSER -p --local --default-character-set=utf8 [DB_NAME] ~/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的代码和了解其实现原理;




原创粉丝点击