使用JWPL (Java Wikipedia Library)操做維基百科數據

使用JWPL (Java Wikipedia Library)操做維基百科數據html

1. JWPL介紹

  JWPL(Java Wikipedia Library)是一個開源的訪問wikipeida數據的Java API包,提供了快速訪問維基百科中包含的消息,如重定向、類別、文章和連接結構的結構性訪問接口。它提供的DataMachine 工具類可快速解析wiki格式文件,生成mysql的數據txt文件,可經過mysqlimport 導入到本地數據庫中。java

  JWPL介紹官網:https://dkpro.github.io/dkpro-jwpl/mysql

  JWPL的源碼:https://github.com/dkpro/dkpro-jwplgit

  JWPL的核心功能包括:1)快速有效地訪問維基百科數據;2)分析處理Wiki格式數據;3)能夠處理任何語言。github

      除了以上列出的核心功能外,JWPL對存在編輯的歷史數據的版本有再現的功能,這些版本再現工具備如下功能:1)從新生成某個歷史時刻的維基百科數據(Time Machine);2)訪問維基百科全部的版本信息(Revision Machine);3)專用的版本存儲格式。sql

2. JWPL解析Wiki數據

  這裏主要介紹如何搭建起使用JWPL那幾個核心功能的平臺,不包括後面利用版本數據的那幾個工具。shell

  JWP核心API訪問的數據都是存儲在mysql數據庫中的結構化的數據。因此,重點就是要怎麼樣把最原始的wikipeida dump數據轉換成mysql數據庫的記錄格式,並導入mysql中,主要利用的就是JWPL提供的數據轉換工具---DataMachine。數據庫

2.1下載維基百科歷史數據

  從Wikipedia dump處下載須要的數據,選擇語言[LANGCODE]和dump日期[DATE]: http://dumps.wikimedia.org/windows

  【注:Wikipedia數據也可直接到Wikipedia的ftp下載,省去找數據麻煩:ftp://wikipedia.c3sl.ufpr.br/wikipedia/,打開這地址後,選擇你想要的版本(其中,enwiki表示英文版,zhwiki表示中文版),注意下載時,後面的名字要徹底匹配,例以下pages-articles.xml.bz2時不要選擇pages-articles-multistream.xml.bz2,由於按照本文方法不能解析multistream版本的api

  最起碼要下載下面三個文件:

 [LANGCODE]wiki-[DATE]-pages-articles.xml.bz2
 [LANGCODE]wiki-[DATE]-pagelinks.sql.gz
 [LANGCODE]wiki-[DATE]-categorylinks.sql.gz

   把該文件放入一個目錄中,好比~/en2012

2.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 文件,下載。

2.3經過下載的DataMachine jar包 解析下載的歷史數據

  命令:

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, chinese
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

  注:按照上述地址下載的DataMachine jar包名稱會比給出的例子中的名稱長,故須要把java命令行中的jar文件用完整的文件名錶示便可,例如我下載的jar包文件名爲:de.tudarmstadt.ukp.wikipedia.datamachine-0.9.2-jar-with-dependencies.jar,則相應的命令行應是:

java -Xmx2g  -cp de.tudarmstadt.ukp.wikipedia.datamachine-0.9.2-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.

java  -Xmx4g -Dfile.encoding=utf8  -cp de.tudarmstadt.ukp.wikipedia.datamachine-0.9.2-jar-with-dependencies.jar
de.tudarmstadt.ukp.wikipedia.datamachine.domain.JWPLDataMachine english Contents Disambiguation_pages ~/en2012

  DataMachine jar解析維基百科數據會須要運行很長時間,大概一成天也有可能。運行完會在SOURCE_DIRECTORY目錄下生成一個output目錄,該目錄裏面有11個文件,這11個文件就是須要導入到mysql中的結構化數據了。

  注意:SOURCE_DIRECTORY 下還會產生一些.bin文件,這些都是臨時文件,程序運行完就能夠把他們刪除了。

2.4建立相應的mysql數據庫

  mysql版本:5.0+【因爲數據量很大,因此最好選擇磁盤空餘空間100g+的磁盤安裝mysql或者設置mysql data的存儲空間】

  建立數據庫命令(數據庫名DB_NAME能夠自行設定):注意要保證建立的數據庫的編碼是utf-8

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

  建立全部的表,下載包含全部表結構的sql腳本:jwpl_tables.sql腳本,在mysql命令下執行改腳本:

mysql> use [DB_NAME];
mysql> source jwpl_tables.sql;  #注意jwpl_tables.sql所在的路徑

  

  導入output目錄下的文件數據(.txt)到mysql數據庫中:

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

  注意:若是導入出現問題,由於有些環境可能不支持通配符批量導入,那就能夠在mysql命令行下利用load data infile一個表一個表導入,如:

mysql> load data infile 'E:/aawiki/output/Category.txt' into table category;

  將數據導入到對應的table中,所須要的時間也很長。

  各個表的結構:

 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:***暫無信息

3. 在Eclipse中使用JWPL jar包去訪問維基百科數據

(1)下載JWPL Wikipedia API

  直接去maven庫中下載整個jar-with-dependencies.jar。下載地址:http://search.maven.org/#search|ga|1|tudarmstadt.ukp

  搜索de.tudarmstadt.ukp.wikipedia.api對應的 jar-with-dependencies.jar 文件,下載。

  【注意:這個de.tudarmstadt.ukp.wikipedia.api對應的jar包和2.2中的de.tudarmstadt.ukp.wikipedia.datamachine對應的jar包不同,前者是在集成開發環境中操做wikipedia數據所須要用到的包,後者是將維基百科數據轉換爲mysql數據庫中的數據所須要用到的包。

(2)下載JWPL的源碼

  由於JWPL是一個開源的項目,因此能夠下載其源碼,而後導入Eclipse中後,可查看其源碼。

  下載地址:https://github.com/dkpro/dkpro-jwpl

(3)在Eclipse中使用JWPL jar包

  在Eclipse中建立一個java project,而後導入(1)中下載的jar包(de.tudarmstadt.ukp.wikipedia.api-1.0.0-jar-with-dependencies.jar):

導入(2)中下載的JWPL源碼(dkpro-jwpl-master.zip),導入後能夠直接使用F3查看源碼:

(4)在Eclipse中使用JWPL jar包去訪問維基百科數據

示例代碼1:顯示頁面信息

 1 import de.tudarmstadt.ukp.wikipedia.api.Category;
 2 import de.tudarmstadt.ukp.wikipedia.api.DatabaseConfiguration;
 3 import de.tudarmstadt.ukp.wikipedia.api.Page;
 4 import de.tudarmstadt.ukp.wikipedia.api.Title;
 5 import de.tudarmstadt.ukp.wikipedia.api.WikiConstants.Language;
 6 import de.tudarmstadt.ukp.wikipedia.api.Wikipedia;
 7 
 8 import static de.tudarmstadt.ukp.wikipedia.api.WikiConstants.LF;
 9 
10 public class ShowPageInfo {
11 
12     public static void main(String[] args) throws Exception {
13         // 數據庫鏈接參數配置
14         DatabaseConfiguration dbConfig = new DatabaseConfiguration();
15         dbConfig.setHost("localhost");   //主機名
16         dbConfig.setDatabase("wikidb");  //數據庫名
17         dbConfig.setUser("root");        //訪問數據庫的用戶名
18         dbConfig.setPassword("root");    //訪問數據庫的密碼
19         dbConfig.setLanguage(Language.english);
20         // 建立Wikipedia處理對象
21         Wikipedia wiki = new Wikipedia(dbConfig);
22         String title = "Fruit";
23         Page page = wiki.getPage(title);  
24         // wikipedia頁面的title
25         System.out.println("Queried string       : " + title);
26         System.out.println("Title                : " + page.getTitle());
27         // 是不是消歧頁面
28         System.out.println("IsDisambiguationPage : " + page.isDisambiguation());       
29         // 是不是重定向頁面
30         System.out.println("redirect page query  : " + page.isRedirect());       
31         // 有多少個頁面指向該頁面
32         System.out.println("# of ingoing links   : " + page.getNumberOfInlinks());       
33         // 該頁面指向了多少個頁面
34         System.out.println("# of outgoing links  : " + page.getNumberOfOutlinks());
35         // 該頁面屬於多少個類別
36         System.out.println("# of categories      : " + page.getNumberOfCategories());
37         StringBuilder sb = new StringBuilder();
38         // 頁面的全部重定向頁面
39         sb.append("Redirects" + LF);
40         for (String redirect : page.getRedirects()) {
41             sb.append("  " + new Title(redirect).getPlainTitle() + LF);
42         }
43         sb.append(LF);       
44         // 頁面的所述的全部類別
45         sb.append("Categories" + LF);
46         for (Category category : page.getCategories()) {
47             sb.append("  " + category.getTitle() + LF);
48         }
49         sb.append(LF);
50         // 指向該頁面的全部頁面
51         sb.append("In-Links" + LF);
52         for (Page inLinkPage : page.getInlinks()) {
53             sb.append("  " + inLinkPage.getTitle() + LF);
54         }
55         sb.append(LF);
56         // 該頁面指向的全部頁面
57         sb.append("Out-Links" + LF);
58         for (Page outLinkPage : page.getOutlinks()) {
59             sb.append("  " + outLinkPage.getTitle() + LF);
60         }       
61         System.out.println(sb);
62     }
63 }
View Code

運行的部分結果:

Queried string       : Fruit
Title                : Fruit
IsDisambiguationPage : false
redirect page query  : false
# of ingoing links   : 4454
# of outgoing links  : 811
# of categories      : 10
View Code

 

示例代碼2:顯示類別信息

 1 import de.tudarmstadt.ukp.wikipedia.api.Category;
 2 import de.tudarmstadt.ukp.wikipedia.api.DatabaseConfiguration;
 3 import de.tudarmstadt.ukp.wikipedia.api.Page;
 4 import de.tudarmstadt.ukp.wikipedia.api.WikiConstants.Language;
 5 import de.tudarmstadt.ukp.wikipedia.api.Wikipedia;
 6 import static de.tudarmstadt.ukp.wikipedia.api.WikiConstants.LF;
 7 
 8 public class ShowCategoryInfo {
 9     public static void main(String[] args) throws Exception {
10         //鏈接數據庫的配置
11         DatabaseConfiguration dbConfig = new DatabaseConfiguration();
12         dbConfig.setHost("localhost");
13         dbConfig.setDatabase("wikidb");
14         dbConfig.setUser("root");
15         dbConfig.setPassword("root");
16         dbConfig.setLanguage(Language.english);
17         // 建立Wikipedia處理對象
18         Wikipedia wiki = new Wikipedia(dbConfig);
19         String title = "Towns in Germany";
20         // 建立類對象
21         Category cat = wiki.getCategory(title);
22         StringBuilder sb = new StringBuilder();
23         // 類別名
24         sb.append("Title : " + cat.getTitle() + LF);
25         sb.append(LF);
26         // 類別的父類信息
27         sb.append("# super categories : " + cat.getParents().size() + LF);
28         for (Category parent : cat.getParents()) {
29             sb.append("  " + parent.getTitle() + LF);
30         }
31         sb.append(LF);       
32         // 類別的子類信息
33         sb.append("# sub categories : " + cat.getChildren().size() + LF);
34         for (Category child : cat.getChildren()) {
35             sb.append("  " + child.getTitle() + LF);
36         }
37         sb.append(LF);
38         // 類別下的全部頁面
39         sb.append("# pages : " + cat.getArticles().size() + LF);
40         for (Page page : cat.getArticles()) {
41             sb.append("  " + page.getTitle() + LF);
42         }       
43         System.out.println(sb); 
44     }
45 }
View Code

運行的結果:

Title : Towns in Germany

# super categories : 4
  Towns by country
  Commons category with local link same as on Wikidata
  Populated places in Germany
  Municipalities of Germany

# sub categories : 16
  Towns in Rhineland-Palatinate
  Towns in Lower Saxony
  Towns in Saxony
  Towns in Mecklenburg-Vorpommern
  Towns in Saxony-Anhalt
  University towns in Germany
  Towns in Schleswig-Holstein
  Seaside resorts in Germany
  Towns in Baden-Württemberg
  Towns in Thuringia
  Towns in Hesse
  Towns in Saarland
  Towns in North Rhine-Westphalia
  Towns in Brandenburg
  Spa towns in Germany
  Towns in Bavaria

# pages : 2
  Oberreichenbach
  Urfeld am Walchensee
View Code

 

【注】在最初程序運行的時候會報各類各樣的debug錯誤提示,這是因爲咱們直接從下載的數據庫腳本中恢復出的數據庫中有各類信息的丟失,好比index,foreign key constraints等,此時,應按照提示的debug信息對相應的數據庫表進行操做。好比我碰到的錯誤提示有:

DEBUG SchemaUpdate:226 - create index nameIndex on Page (name)

解決辦法:直接按照提示在數據庫中對錶Page中的name列建立索引。

mysql> create index nameIndex on Page (name);

4. 資源

在此放上一些相關的資源,不包括維基百科歷史數據,由於數據量太大了。

使用JWPL操做維基百科數據:https://yunpan.cn/cYvBsCxs79J8T  訪問密碼 749f

5. 感謝

Alex He使用JWPL工具操做wikipedia數據

zhong36060123的使用JWPL工具操做wikipedia數據

相關文章
相關標籤/搜索