Wikidata数据结构

Wikidata的JSON版本数据结构以及一些相关的信息记录。

下载

Wikidata官方版本下载地址

基本每隔几天都会更新一次,里面有几种格式的数据,包括JSON dump (.json文件),RDF dump (使用Turtle和NTriples格式的.nt和.ttl文件),XML dump (在另一个地址里)。

另外wikidata从2018年开始增加了一种namespace为lexeme的item,官方解释为:

In linguistics, a lexeme is a unit of lexical meaning. Similarly, Wikidata's lexemes are items with a structure that makes them more suitable to store lexicographical data. Besides storing the language to which the lexeme refers, they have a section for forms and a section for senses.

意思似乎跟中文中的义原 (sememe) 比较像,这些新的数据也以三种格式保存在前面的地址。

目前 (2022.01.26) 最新版的wikidata JSON版本的压缩包已经到达接近70G,解压之后有几百G,而且是存在一个文件里的,比较难以处理。如果想用较少数据熟悉一下wikidata可以下载以前的版本)。只是下载速度会比较慢。

JSON文件结构

wikidata的JSON文件结构具体说明见这里

上层结构

Wikidata里主要保存两类entity,分别是item和property,其中item用于记录各类实体,property用于表述实体的属性,二者的区别首先由属性type决定,其次property没有sitelinks,但多了datatype。

item上层结构如:

1
2
3
4
5
6
7
8
9
10
11
{
"id": "Q60",
"type": "item",
"labels": {},
"descriptions": {},
"aliases": {},
"claims": {},
"sitelinks": {},
"lastrevid": 195301613,
"modified": "2020-02-10T12:42:02Z"
}

property上层结构如:

1
2
3
4
5
6
7
8
9
10
11
{
"id": "P30",
"type": "property",
"datatype": "wikibase-item"
"labels": {},
"descriptions": {},
"aliases": {},
"claims": {},
"lastrevid": 195301614,
"modified": "2020-02-10T12:42:02Z"
}

各项内容说明如下:

  • id:表示该实体的唯一性ID,其中item以Q开头,property以P开头;
  • type:表示该实体为item或property;
  • datatype:property实体适用的数据类型;
  • labels:不同语言中的label (即不同语言中对这个entity的表述方式);
  • descriptions:不同语言中对这个entity的描述;
  • aliases:不同语言中对这个词的其他表述方式 (或者理解为同义词);
  • claims:关于该实体的statement (若干,每个由一个property作为key,可以理解为该实体的一条属性);
  • sitelinks:多个包括该实体 (item) 的网页链接。

Labels, Descriptions and Aliases

下面给出一个具体的labels、descriptions和aliases的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{
"labels": {
"en": {
"language": "en",
"value": "New York City"
},
"ar": {
"language": "ar",
"value": "\u0645\u062f\u064a\u0646\u0629 \u0646\u064a\u0648 \u064a\u0648\u0631\u0643"
}
},
"descriptions": {
"en": {
"language": "en",
"value": "largest city in New York and the United States of America"
},
"it": {
"language": "it",
"value": "citt\u00e0 degli Stati Uniti d'America"
}
},
"aliases": {
"en": [
{
"language": "en",
"value": "New York"
},
],
"fr": [
{
"language": "fr",
"value": "New York City"
},
{
"language": "fr",
"value": "NYC"
},
{
"language": "fr",
"value": "The City"
},
{
"language": "fr",
"value": "La grosse pomme"
}
]
}
}

其中每个元素都由一个language属性和实际的value组成,其中aliases以语言作为key,每个语言下对应的是一个该语言的同义词的list (表中每个元素仍然符合上述规则)。

Statements

下面给出一个statements的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"claims": {
"P17": [
{
"id": "q60$5083E43C-228B-4E3E-B82A-4CB20A22A3FB",
"mainsnak": {},
"type": "statement",
"rank": "normal",
"qualifiers": {
"P580": [],
"P5436": []
}
"references": [
{
"hash": "d103e3541cc531fa54adcaffebde6bef28d87d32",
"snaks": []
}
]
}
]
}
}

其结构是一个以property id为key的map,每个statement (或称为claim) 表示当前实体的一个属性 (property),其中包括的信息如下:

  • id:用于表示该statement的全局单一的随机ID;
  • type:只能填statement (历史版本中也可能填claim);
  • mainsnak:用于表示与当前property相关的value的Snak,注意其中包括的property要与作为key的property一致;
  • rank:表示该值是否会在query中显示 (preferred, normal or deprecated);
  • qualifiers:对主要value的补充描述 (例如测量时间等);
  • references:记录mainsnak中数据的来源。

注意:在历史版本的wikidata中,statement和claim有所区别,前者有reference而后者没有。但新版中二者不做区分。

Snak

下面给出一个statements中的mainsnak的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"claims": {
"P17": [
{
"mainsnak": {
"snaktype": "value",
"property": "P17",
"datatype": "wikibase-item",
"datavalue": {
"value": {
"entity-type": "item",
"id": "Q30",
"numeric-id": 30
},
"type": "wikibase-entityid"
}
},
},
{
"mainsnak": {
"snaktype": "somevalue",
"property": "P17",
},
}
],
"P356": [
{
"mainsnak": {
"snaktype": "value",
"property": "P356",
"datatype": "string",
"datavalue": {
"value": "SomePicture.jpg",
"type": "string"
}
},
}
]
}
}

其中包括信息有:

  • snaktype:value, somevalue or novalue,其中value表示具体的值,另外两个则表示当前snak有某个未知值或者没有值;
  • property:相关property的id;
  • datatype:数据的类别,所有类别定义,来自property的datatype;
  • datavalue:只有当snaktype为value时有这一项,表示property具体的值。

Data Values

下面给出data value的例子:

1
2
3
4
5
6
7
8
9
10
11
12
"datavalue": {
"value": {
"entity-type": "item",
"id": "Q30",
"numeric-id": 30
},
"type": "wikibase-entityid"
}
"datavalue": {
"value": "SomePicture.jpg",
"type": "string"
}

其中包括两个主要属性:

  • type:描述值的数据类型,该类型只用于处理文本。例如一个link的data type可能是url,但value中的type应该是string
  • value:具体的值,可能是数字,字符串或更复杂的结构。

接下来具体介绍几种value的类别。

string

1
2
3
4
"datavalue": {
"value": "SomePicture.jpg",
"type": "string"
}

string类型的value只包括简单的字符串常量。

wikibase-entityid

1
2
3
4
5
6
7
8
"datavalue": {
"value": {
"entity-type": "item",
"id": "Q30",
"numeric-id": 30
},
"type": "wikibase-entityid"
}

wikibase-entityid类型的value包括:

  • entity-type:目标entity的类别 (item or property);
  • id:目标entity的唯一ID;
  • numeric-id:ID的数字部分。(注意:并不是所有的entity都有数字ID,因此建议使用id)

globecoordinate

1
2
3
4
5
6
7
8
9
10
"datavalue": {
"value": {
"latitude": 52.516666666667,
"longitude": 13.383333333333,
"altitude": null,
"precision": 0.016666666666667,
"globe": "http:\/\/www.wikidata.org\/entity\/Q2"
},
"type": "globecoordinate"
}

globecoordinate (全球坐标) 类型的value包括:

  • latitude:纬度;
  • longitude:经度;
  • precision:准确率;
  • globe:对应地点的URI (例如Q2 = earth);
  • altitude:DEPRECATED。

quantity

1
2
3
4
5
6
7
8
9
"datavalue": {
"value":{
"amount":"+10.38",
"upperBound":"+10.375",
"lowerBound":"+10.385",
"unit":"http://www.wikidata.org/entity/Q712226"
},
"type":"quantity"
}

quantity类型的value包括:

  • amount:具体值,开头正负号表示值的正负性;
  • upperBound/lowerBound:上下界,必须同时出现,如果未给出说明该值的不确定性未知;
  • unit:单位的URI。(例如这里的Q712226 = square kilometer,如果没有单位则为”1”)

time

1
2
3
4
5
6
7
8
9
10
11
"datavalue": {
"value": {
"time": "+2001-12-31T00:00:00Z",
"timezone": 0,
"before": 0,
"after": 0,
"precision": 11,
"calendarmodel": "http:\/\/www.wikidata.org\/entity\/Q1985727"
},
"type": "time"
}

time类型的value包括:

  • time:具体时间;
  • timezone:时区;
  • calendarmodel:日历模型的URI,例如gregorian or julian;
  • precision:To what unit is the given date/time significant,用数字代号表示;
  • before/after:目前未使用。

其他

其他没有涉及到的还有Qualifiers,References和Sitelinks,其基本信息已经在开头介绍了,具体信息见英文说明

利用方法

三元组

总的来说,如果只希望抽取三元组的话,应该关注item类别的entity,然后从其claims里面逐个判断每个property,property的Snak的datavalue的type是wikibase-entityid的表示这一个property描述的是当前item和另一个item之间的关系。抽取这类item-property-item信息作为三元组 (后面需要根据item/property的label属性将其转化为不同语言中的表示)。

qwikidata

qwikidata是一个用于读取wikidata数据的Python library。安装方法如下:

1
pip install qwikidata

使用API

下面是一个qwikidata使用API获取信息的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from qwikidata.entity import WikidataItem, WikidataLexeme, WikidataProperty
from qwikidata.linked_data_interface import get_entity_dict_from_api
# create an item representing "Douglas Adams"
Q_DOUGLAS_ADAMS = "Q42"
q42_dict = get_entity_dict_from_api(Q_DOUGLAS_ADAMS)
q42 = WikidataItem(q42_dict)
# create a property representing "subclass of"
P_SUBCLASS_OF = "P279"
p279_dict = get_entity_dict_from_api(P_SUBCLASS_OF)
p279 = WikidataProperty(p279_dict)
# create a lexeme representing "bank"
L_BANK = "L3354"
l3354_dict = get_entity_dict_from_api(L_BANK)
l3354 = WikidataLexeme(l3354_dict)

读取本地JSON文件

下面是一个读取本地Wikidata JSON文件的例子 (例子中实现的是搜索职业为政客的人):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import time
from qwikidata.entity import WikidataItem
from qwikidata.json_dump import WikidataJsonDump
from qwikidata.utils import dump_entities_to_json
P_OCCUPATION = "P106"
Q_POLITICIAN = "Q82955"
def has_occupation_politician(item: WikidataItem, truthy: bool = True) -> bool:
"""Return True if the Wikidata Item has occupation politician."""
if truthy:
claim_group = item.get_truthy_claim_group(P_OCCUPATION)
else:
claim_group = item.get_claim_group(P_OCCUPATION)
occupation_qids = [
claim.mainsnak.datavalue.value["id"]
for claim in claim_group
if claim.mainsnak.snaktype == "value"
]
return Q_POLITICIAN in occupation_qids
# create an instance of WikidataJsonDump
wjd_dump_path = "wikidata-20190401-all.json.bz2"
wjd = WikidataJsonDump(wjd_dump_path)
# create an iterable of WikidataItem representing politicians
politicians = []
t1 = time.time()
for ii, entity_dict in enumerate(wjd):
if entity_dict["type"] == "item":
entity = WikidataItem(entity_dict)
if has_occupation_politician(entity):
politicians.append(entity)
if ii % 1000 == 0:
t2 = time.time()
dt = t2 - t1
print(
"found {} politicians among {} entities [entities/s: {:.2f}]".format(
len(politicians), ii, ii / dt
)
)
if ii > 10000:
break
# write the iterable of WikidataItem to disk as JSON
out_fname = "filtered_entities.json"
dump_entities_to_json(politicians, out_fname)
wjd_filtered = WikidataJsonDump(out_fname)
# load filtered entities and create instances of WikidataItem
for ii, entity_dict in enumerate(wjd_filtered):
item = WikidataItem(entity_dict)

Wikipedia

wikipedia是一个用于获取Wikipedia信息的Python library。
安装方法如下:

1
pip install wikipedia

下面是一个使用wikipedia获取相应title的信息的例子,其中summary对应的应该就是整个data.content里的第一段 (一般是对这个title的总结性描述),可以通过参数sentences控制显示summary的前几句。另外在查询其他语言的title之前需要先用set_lang转换语言,支持的所有语言数量可以用wikipedia.languages()查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
import wikipedia
def search(title, lan):
wikipedia.set_lang(lan)
data = wikipedia.page(title)
sum = wikipedia.summary(title, sentences=2)
print ("@Title: ", data.title)
print ("@Summary: ", sum)
print ("@Content:", data.content[:256])
search("奥巴马", "zh")
search("Obama", "en")

下面是上述例子的输出:

1
2
3
4
5
6
7
@Title: 贝拉克·奥巴马
@Summary: 巴拉克·侯赛因·奥巴马二世(英語:Barack Hussein Obama II,美國 /bəˈrɑːk huːˈseɪn oʊˈbɑːmə/,1961年8月4日-),是一名美国政治家,民主黨籍,從2009年至2017年期間擔任第44任美国总统。他是首位擁有非裔血統的美国总统。
@Content: 巴拉克·侯赛因·奥巴马二世(英語:Barack Hussein Obama II,美國 /bəˈrɑːk huːˈseɪn oʊˈbɑːmə/,1961年8月4日-),是一名美国政治家,民主黨籍,從2009年至2017年期間擔任第44任美国总统。他是首位擁有非裔血統的美国总统。2005年至2008年代表伊利诺伊州担任聯邦參議員,从1997年至2004年担任伊利诺伊州参议员時居於芝加哥。卸任總統後,定居首都华盛頓特區。
奥巴马生於美国夏威夷州檀香山,他在夏威夷长大,但童年时期也在华盛顿州和印尼分别生活一年和四
@Title: Barack Obama
@Summary: Barack Hussein Obama II ( (listen) bə-RAHK hoo-SAYN oh-BAH-mə; born August 4, 1961) is an American politician, lawyer, and author who served as the 44th president of the United States from 2009 to 2017. A member of the Democratic Party, Obama was the first African-American president of the United States.
@Content: Barack Hussein Obama II ( (listen) bə-RAHK hoo-SAYN oh-BAH-mə; born August 4, 1961) is an American politician, lawyer, and author who served as the 44th president of the United States from 2009 to 2017. A member of the Democratic Party, Obama was the first

另外需要注意的是如果输入的title有歧义 (即可能对应多个wikipedia页面) 或者不存在,上述的命令都会报错。

结合Wikidata使用

Wikidata的labels下面每个元素是一个languagevalue组成的结构,其中value对应的应该就是wikipedia里的title,而language也就是对应的语言。因此对labels里的每个language-value对直接调用上面例子里的search(value,language)就可以获取对应的data。

1
2
3
4
5
6
7
8
9
"labels": {
"en": {
"language": "en",
"value": "New York City"
},
"zh": {
"language": "zh",
"value": "奥巴马"
}