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的代碼和了解其實現原理;