Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add wikibase, wikibase_item, entities and claims.
Wikibase and wikibase_item(): >>> import mwclient >>> site = mwclient.Site(('https', 'fr.wikipedia.org')) >>> p = site.Pages['Nicolas Sarkozy'] >>> p.wikibase_item() <Item object Q329 (('https', u'www.wikidata.org'))> >>> site.wikibase() <WikiBaseSite object '('https', u'www.wikidata.org')/w/'> Added entities() to WikiBaseSite It works this way >>> import mwclient >>> site = mwclient.WikiBaseSite(('https', 'www.wikidata.org')) >>> ent = site.entities('Q422') >>> q422 = ent[0] >>> q422 <Item object Q422 (('https', 'www.wikidata.org'))> >>> q422.claims() Fetching labels, descriptions and sitelinks for entities >>> import mwclient >>> site = mwclient.WikiBaseSite(('https', 'www.wikidata.org')) >>> q = mwclient.entity.Item(site, 'Q42') >>> q.sitelinks >>> q.labels >>> q.descriptions ids filter for entities(): >>> import mwclient >>> wikidata = mwclient.WikiBaseSite(('https', 'www.wikidata.org')) >>> entities = wikidata.entities(ids=['Q42', 'P238']) >>> for entity in entities: >>> print entity <Property object P238 (('https', 'www.wikidata.org'))> <Item object Q42 (('https', 'www.wikidata.org'))> Property filter in claims(): >> import mwclient >> site = mwclient.Site(('https', 'en.wikipedia.org')) >> article = site.Pages['Nicolas Sarkozy'] >> item = article.wikibase_item() >> #only distinction >> for claim in item.claims(prop=['P166']): >> print claim >> # All Claims >> for claim in item.claims(): >> print claim Claim object have now both properties: * `snaktype` * `value` set to `None` if `snaktype` is either `somevalue` or `novalue`
- Loading branch information
1 parent
b813deb
commit f0f20fa
Showing
4 changed files
with
355 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,281 @@ | ||
"""WikiBase Entities and related objects.""" | ||
|
||
|
||
class Entity(object): | ||
|
||
"""Wikibase Entity, either Item or Property. | ||
This class should not be implemented directly, | ||
It is meant to be abstract for Item and Property. | ||
Attributes: | ||
site (WikiBaseSite): reference to a WikiBaseSite | ||
entity (str): Q number of the entity. | ||
descriptions (dict): dictionnary containing description per language | ||
labels (dict): dictionnary containing labels per language | ||
""" | ||
|
||
def __init__(self, site, normalized_entity): | ||
"""Common part of constructor for Item and Property.""" | ||
self.site = site | ||
|
||
self.entity = normalized_entity | ||
# caching descriptions, labels, sitelinks | ||
# self._sitelinks = None | ||
self._descriptions = None | ||
self._labels = None | ||
|
||
# caching claims | ||
self._itemclaims = None | ||
|
||
def setinfofromwbgetentities(self, result): | ||
"""Set descriptions, labels and claims from wbgetentities result.""" | ||
self._descriptions = dict() | ||
for language in result['descriptions']: | ||
lang = result['descriptions'][language]['language'] | ||
value = result['descriptions'][language]['value'] | ||
self._descriptions[lang] = value | ||
self._labels = dict() | ||
for language in result['labels']: | ||
lang = result['labels'][language]['language'] | ||
value = result['labels'][language]['value'] | ||
self._labels[lang] = value | ||
if self._itemclaims is None: | ||
self._itemclaims = [] | ||
for prop in result['claims']: | ||
for claim in result['claims'][prop]: | ||
mainsnak = claim['mainsnak'] | ||
self._itemclaims.append(Claim.fromsnak(self.site, | ||
mainsnak)) | ||
|
||
@property | ||
def labels(self): | ||
"""Labels dictionnary per language""" | ||
if self._labels is None: | ||
entities = self.site.api('wbgetentities', ids=self.entity) | ||
result = entities['entities'][self.entity] | ||
self.setinfofromwbgetentities(result) | ||
return self._labels | ||
|
||
@property | ||
def descriptions(self): | ||
"""Descriptions dictionnary per language""" | ||
if self._descriptions is None: | ||
entities = self.site.api('wbgetentities', ids=self.entity) | ||
result = entities['entities'][self.entity] | ||
self.setinfofromwbgetentities(result) | ||
return self._descriptions | ||
|
||
def claims(self, prop=None): | ||
"""Claims about an Entity. | ||
API Doc: https://www.mediawiki.org/wiki/Wikibase/API/en#wbgetclaims | ||
We will probably need to implement rank and props later on. | ||
Args: | ||
prop (list, optional): list of property e.g. ['P238', 'P239'] | ||
""" | ||
if self._itemclaims is None: | ||
self._itemclaims = [] | ||
info = self.site.api('wbgetclaims', entity=self.entity)['claims'] | ||
|
||
for propid in info: | ||
for claim in info[propid]: | ||
mainsnak = claim['mainsnak'] | ||
self._itemclaims.append(Claim.fromsnak(self.site, | ||
mainsnak)) | ||
if prop is None: | ||
return self._itemclaims | ||
else: | ||
return [claim for claim in self._itemclaims if claim.prop in prop] | ||
|
||
|
||
class Item(Entity): | ||
|
||
"""Wikibase Item. | ||
Attributes: | ||
site (WikiBaseSite): reference to a WikiBaseSite | ||
entity (str): Q number of the entity. | ||
sitelinks (dict): dictionnary containing sitelinks per wiki | ||
descriptions (dict): dictionnary containing description per language | ||
labels (dict): dictionnary containing labels per language | ||
""" | ||
|
||
def __init__(self, site, entity): | ||
"""Constructor. | ||
Args: | ||
site (WikiBaseSite): reference to a WikiBaseSite | ||
entity (str): Q number of the entity. | ||
""" | ||
# Normalizing entity name | ||
super(Item, self).__init__(site, 'Q' + entity.upper().lstrip('Q')) | ||
|
||
self._sitelinks = None | ||
|
||
def setinfofromwbgetentities(self, result): | ||
"""Set sitelinks, descriptions, labels, claims from wbgetentities.""" | ||
super(Item, self).setinfofromwbgetentities(result) | ||
self._sitelinks = dict() | ||
for wiki in result['sitelinks']: | ||
site = result['sitelinks'][wiki]['site'] | ||
title = result['sitelinks'][wiki]['title'] | ||
badges = result['sitelinks'][wiki]['badges'] | ||
self._sitelinks[site] = {'title': title, 'badges': badges} | ||
|
||
@property | ||
def sitelinks(self): | ||
"""Sitelinks dictionnary with title, and badges per site. | ||
Example: | ||
>>> import mwclient | ||
>>> site = mwclient.WikiBaseSite(('https', 'www.wikidata.org')) | ||
>>> q = mwclient.entity.Item(site, 'Q3340172') | ||
>>> q.sitelinks | ||
""" | ||
if self._sitelinks is None: | ||
entities = self.site.api('wbgetentities', ids=self.entity) | ||
result = entities['entities'][self.entity] | ||
self.setinfofromwbgetentities(result) | ||
return self._sitelinks | ||
|
||
def __repr__(self): | ||
"""Item representation.""" | ||
return "<Item object %s (%s)>" % (self.entity, self.site.host) | ||
|
||
|
||
class Property(Entity): | ||
|
||
"""Wikibase Property.""" | ||
|
||
def __init__(self, site, entity): | ||
"""Constructor. | ||
Args: | ||
site (WikiBaseSite): reference to a WikiBaseSite | ||
entity (str): Q number of the entity. | ||
""" | ||
# Normalizing entity name | ||
super(Property, self).__init__(site, 'P' + entity.upper().lstrip('P')) | ||
|
||
def __repr__(self): | ||
"""Property representation.""" | ||
return "<Property object %s (%s)>" % (self.entity, self.site.host) | ||
|
||
|
||
class Claim(object): | ||
|
||
"""Claim | ||
Attributes: | ||
prop (str): property id. | ||
snak (dict): snak with all values return in mainsnak from API call. | ||
snaktype (str): 'value', 'somevalue' or 'novalue' | ||
datatype (str): datatype ('wikibase-item', 'string', etc.) | ||
value (dict): content of snak['datavalue']['value'] if snaktype is | ||
'value', None othewise. | ||
string (str): string value, None if not 'string' datatype | ||
item (Item): Item value, None if not 'wikibase-item' datatype | ||
property_value (Property): Property, None if not 'wikibase-property' | ||
datatype | ||
latitude (float): latitude, None if not 'globe-coordinate' datatype | ||
longitude (float): longitude, None if not 'globe-coordinate' datatype | ||
quantity (dict): quantity dictionnary, None if not 'quantity' datatype | ||
""" | ||
|
||
def __init__(self, site, prop, datatype, snaktype, value=None, snak=None): | ||
"""Constructor""" | ||
self.site = site | ||
self.prop = prop | ||
self.datatype = datatype | ||
self.value = value | ||
self.snaktype = snaktype | ||
self.snak = snak | ||
|
||
@classmethod | ||
def fromsnak(cls, site, snak): | ||
"""Claim from snak dictionnary. | ||
Args: | ||
site (mwclient.WikiBaseSite): site | ||
snak (dict): snak dictionnary | ||
""" | ||
snakvalue = None | ||
if snak['snaktype'] == 'value': | ||
snakvalue = snak['datavalue']['value'] | ||
return cls(site, snak['property'], | ||
snak['datatype'], | ||
snak['snaktype'], | ||
value=snakvalue, | ||
snak=snak) | ||
|
||
def __repr__(self): | ||
"""Representation.""" | ||
return "<Claim object %s [%s]>" % (self.prop, self.datatype) | ||
|
||
@property | ||
def string(self): | ||
"""String | ||
String value if datatype is 'string', None otherwise | ||
""" | ||
stringvalue = None | ||
if self.datatype == "string": | ||
stringvalue = self.value | ||
return stringvalue | ||
|
||
@property | ||
def item(self): | ||
"""Item. | ||
Item if datatype is 'wikibase-item', None otherwise | ||
""" | ||
item = None | ||
if self.datatype == 'wikibase-item': | ||
item = Item(self.site, str(self.value['numeric-id'])) | ||
return item | ||
|
||
@property | ||
def property_value(self): | ||
"""Property. | ||
Property if datatype is 'wikibase-property', None otherwise. | ||
""" | ||
prop = None | ||
if self.datatype == 'wikibase-property': | ||
prop = Property(self.site, str(self.value['numeric-id'])) | ||
return prop | ||
|
||
@property | ||
def latitude(self): | ||
"""Latitude (in degree decimal) | ||
Latitude if datatype is 'globe-coordinate', None otherwise. | ||
""" | ||
latitude = None | ||
if self.datatype == 'globe-coordinate': | ||
latitude = self.value['latitude'] | ||
return latitude | ||
|
||
@property | ||
def longitude(self): | ||
"""Longitude (in degree decimal) | ||
Longitude if datatype is 'quantity', None otherwise. | ||
""" | ||
longitude = None | ||
if self.datatype == 'globe-coordinate': | ||
longitude = self.value['longitude'] | ||
return longitude | ||
|
||
@property | ||
def quantity(self): | ||
"""Quantity. | ||
Quantity if datatype is 'quantity', None otherwise. | ||
""" | ||
quantity = None | ||
if self.datatype == 'quantity': | ||
quantity = self.value | ||
return quantity |
Oops, something went wrong.