Wikidata:ボットの作成
このページでは、ウィキデータのためのボットを作成する方法について説明しています。新たな使用事例の追加や改変の提案、あなたの持っているコードの共有をぜひ検討してください。
要件
ボットを作成ために必要なのは:
- コーディングスキル (Python, Perl, PHP...)
- フレームワーク (下記のうちひとつ) とタスクの実行と完了コード
- ボットアカウント (使用申請によるフラグも必要)
- ソースコードエディタ (Notepad++, Geany, vim, emacs)
推奨
- Wikidata telegram channelの議論に参加してください。プログラミングについての質問もできます。
Pywikibot
警告: 2022年6月現在、このbotの語彙素のサポートは不完全です。完全にサポートしているものは以下の通りです。 |
ここではインストール、設定、pywikibotを使用してログインする方法を案内しています。これら3つのステップを実行する必要があるのは、初回だけです。また、ボットのプログラミングの基礎を知るための、いくつかの基本的な事例を紹介します。
インストール
- pywikibotインストールの詳細についてはmw:Manual:Pywikibot/InstallationとWikidata:Pywikibot - Python 3 Tutorial/Setting up Shopを参照
- pywikibotをインストールせず使うには、mw:Manual:Pywikibot/PAWSを参照
pywikibotのインストール:
- Pythonをインストールする(バージョンは3.5.2以降が必須です。)
- pywikibotをダウンロードする
- zipファイルとしてダウンロード
- もしくは、gitリポジトリ経由:Manual:Pywikibot/Gerrit
設定
- pywikibot設定の詳細はmw:Manual:Pywikibot/user-config.pyを参照。
ボットのユーザ名、対象のプロジェクトと言語をuser-config.py
で設定しなければなりません。ウィキデータではプロジェクトと言語のパラメータは同じくwikidata
となります。
Extended content |
---|
mylang = "wikidata"
family = "wikidata"
usernames["wikidata"]["wikidata"] = 'MyBotName'
|
以下を追記すると遅延間隔を減らすことができます: put_throttle = 1
ログイン
user-config.py
ファイルで設定を済ませた後、以下のようにログインします:
$ python login.py
ボットのパスワードを質問されたら入力してエンターキーを押してください。そうすれば、ログイン状態になっているはずです。
例1: データの取得
この例はダグラス・アダムズを指すページに対するデータを取得します。次のソースコードをファイルに保存してpython example1.pyを実行してください。
Extended content |
---|
import pywikibot
site = pywikibot.Site("en", "wikipedia")
page = pywikibot.Page(site, 'Douglas Adams')
item = pywikibot.ItemPage.fromPage(page)
dictionary = item.get()
print(dictionary)
print(dictionary.keys())
print(item)
|
item.get()
はウィキデータへ接続してデータを取得します。その出力(読み易く再成形済み)は:
{ 'claims': { 'P646': [<pywikibot.page.Claim instance at 0x7f1880188b48>], 'P800': [<pywikibot.page.Claim instance at 0x7f1880188488>, <pywikibot.page.Claim instance at 0x7f1880188368>] ... } 'labels': { 'gu': '\u0aa1\u0a97\u0acd\u0ab2\u0abe\u0ab8 \u0a8f\u0aa1\u0aae\u0acd\u0ab8', 'scn': 'Douglas Adams', ... } 'sitelinks': { 'fiwiki': 'Douglas Adams', 'fawiki': '\u062f\u0627\u06af\u0644\u0627\u0633 \u0622\u062f\u0627\u0645\u0632', 'elwikiquote': '\u039d\u03c4\u03ac\u03b3\u03ba\u03bb\u03b1\u03c2 \u0386\u03bd\u03c4\u03b1\u03bc\u03c2', ... } 'descriptions': { 'eo': 'angla a\u016dtoro de sciencfikcio-romanoj kaj humoristo', 'en': 'English writer and humorist', }, 'aliases': { 'ru': ['\u0410\u0434\u0430\u043c\u0441, \u0414\u0443\u0433\u043b\u0430\u0441'], 'fr': ['Douglas Noel Adams', 'Douglas No\xebl Adams'], ... } } ['claims', 'labels', 'sitelinks', 'descriptions', 'aliases'] [[wikidata:Q42]]
以下のキーで辞書が出力されます:
- ページの主張のセット:Freebase識別子Property:P646、「主な作品Property:P800など
- 項目のラベルを多言語で
- 項目のサイトリンクを、多言語版ウィキペディアだけでなく、多言語版ウィキクオートも
- 項目の説明を多言語で
- 項目の別名を多言語で
その後、辞書のキーと値の組に対するすべてのキーのリスト。 最後に、ダグラス・アダムズに関するウィキデータ項目がQ42であると確認できます。
代替策
上記の例は英語版ウィキペディアの記事を使ってItemPageを取得しました。その代わりに、直接ItemPageを取得することもできます:
Extended content |
---|
import pywikibot
site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, 'Q42')
|
例2: ウィキ間リンクの取得
item.get() (接続と取得開始)に続き、例えばサイトリンクを読み出すとします。記事のあるウィキペディア群へのリンクを取得します。
Extended content |
---|
import pywikibot
site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, 'Q42')
item.get()
print(",".join(item.sitelinks))
|
以下がその出力です。
{'fiwiki': 'Douglas Adams', 'eowiki': 'Douglas Adams', 'dewiki': 'Douglas Adams', ...}
item.iterlinks() を使い、上記のサイトリンクすべてに対するイテレータ(反復子)を返すことで、前例とは異なり、記事ごとにプレーンテキストではなくページオブジェクトとして次の処理に渡せる形で出力します(例えば引き続き、ウィキペディアの対応する記事中でテキスト編集に用いるなど)。
例4: 説明の設置
この例では、ダグラス・アダムズについての、英語およびドイツ語の説明を設定します。
Extended content |
---|
import pywikibot
site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, 'Q42')
item.get()
mydescriptions = {'en': 'English writer and humorist', 'de': 'Keine Panik!'}
item.editDescriptions(mydescriptions, summary='Setting/updating descriptions.')
|
ラベルと別名の設定はそれに応じて機能します。
例6: サイトリンクの設置
サイトリンクを設けるには、例4に対応するdictを作成するかページオブジェクトを利用します。
Extended content |
---|
import pywikibot
site = pywikibot.Site("en", "wikipedia")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, 'Q42')
page = pywikibot.Page(site, 'Douglas Adams')
item.setSitelink(page, summary='Setting (/updating?) sitelink.')
|
例7: 文の設置
文はClaimクラスを使用して設定されます。以下では、ダグラス・アダムスのplace of birth (P19):Cambridge (Q350)を設定しました。
Extended content |
---|
import pywikibot
site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, 'Q42')
claim = pywikibot.Claim(repo, 'P19')
target = pywikibot.ItemPage(repo, 'Q350')
claim.setTarget(target)
item.addClaim(claim, summary='Adding claim')
|
他のデータ型でも同様に動作します。以下では、IMDb ID (P345)やcoordinate location (P625)を追加します。
Extended content |
---|
import pywikibot
site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, 'Q42')
stringclaim = pywikibot.Claim(repo, 'P345')
stringclaim.setTarget('nm0010930')
item.addClaim(stringclaim, summary='Adding string claim')
coordinateclaim = pywikibot.Claim(repo, 'P625')
coordinate = pywikibot.Coordinate(lat=52.208, lon=0.1225, precision=0.001, site=site)
coordinateclaim.setTarget(coordinate)
item.addClaim(coordinateclaim, summary='Adding coordinate claim')
|
例8: 修飾子の追加
修飾子は文のクラスによっても記述されます。以下では、文にincertae sedis (P678): family (Q35409)を追加します。修飾子を追加する前に忘れずにアイテムを追加してください。
Extended content |
---|
qualifier = pywikibot.Claim(repo, 'P678')
target = pywikibot.ItemPage(repo, "Q35409")
qualifier.setTarget(target)
claim.addQualifier(qualifier, summary='Adding a qualifier.')
|
例9: 情報源の追加
情報源も文のクラスで表現されます。修飾子と異なり、情報源は複数の分を含むことがあります。以下では主張の情報源としてstated in (P248):Integrated Taxonomic Information System (Q82575)とretrieved (P813) March 20, 2014を追加します。文は事前にアイテムに追加されなければならない。
Extended content |
---|
statedin = pywikibot.Claim(repo, 'P248')
itis = pywikibot.ItemPage(repo, "Q82575")
statedin.setTarget(itis)
retrieved = pywikibot.Claim(repo, 'P813')
date = pywikibot.WbTime(year=2014, month=3, day=20)
retrieved.setTarget(date)
claim.addSources([statedin, retrieved], summary='Adding sources.')
|
例10:ページの作成
TODO
例11:サブプロパティの値を取得する
以下では、described by source (P1343) -> Great Soviet Encyclopedia (1969–1978) (Q17378135) -> reference URL (P854)とtitle (P1476)という分枝からサブプロパティの値を取得します。
Extended content |
---|
import pywikibot
site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, 'Q13515')
item.get()
sourcesid = 'P1343'
sourceid = 'Q17378135'
urlid = 'P854'
nameid = 'P1476'
# item.claims['P1343'][1].qualifiers.items(): # This are direct way to get list qualifiers. But '[1]' is hard link to index of list, it will break over time.
if sourcesid in item.claims:
for source in item.claims[sourcesid]:
if source.target.id == sourceid:
s = source.qualifiers
if urlid in s: url = s.get(urlid)[0].target
if nameid in s: name = s.get(nameid)[0].target['text']
print (url, name)
|
その他の例
ソースコードを共有する利用者もいます。詳しくは次のリンクを参照。
- User:RobotMichiel1972/wikidata lowercase.py - pywikipedia example how you can correct the label to lowercase using the English label capitalization as 'reference' (here hard coded implemented for nlwiki only) running over selection of pages in own wikipedia.
- File:Bots hackathon 2013.pdf presenting "claimit.py" and "template_harvest.py" included in the core version (former re-write).
ウィキデータ・インテグレーター
WikidataIntegrator is a library for reading and writing to Wikidata/Wikibase. We created it for populating Wikidata with content from authoritative resources on Genes, Proteins, Diseases, Drugs and others. Details on the different tasks can be found on the bot's Wikidata page.
Pywikibot is an existing framework for interacting with the MediaWiki API. The reason why we came up with our own solution is that we need a high integration with the Wikidata SPARQL endpoint in order to ensure data consistency (duplicate checks, consistency checks, correct item selection, etc.). Compared to Pywikibot, WikidataIntegrator currently is not a full Python wrapper for the MediaWiki API but is solely focused on providing an easy means to generate Python-based Wikidata bots.
For more information, documentation, download & installation instructions, see here: https://github.com/SuLab/WikidataIntegrator/
ノートブックの例
An example notebook demonstrating an example bot to add therapeutic areas to drug items, including using fastrun mode, checking references, and removing old statements:
http://public-paws.wmcloud.org/46883698/example%20ema%20bot.ipynb
WikibaseIntegrator
Forked from Wikidata Integrator by User:Myst in 2020 and has seen several improvements to the API that makes it even easier to create bots using the library.
For more information, documentation, download & installation instructions, see here: https://github.com/LeMyst/WikibaseIntegrator
半自動的スクリプトの例
LexUse semi-automatic tool for finding and adding usage examples to lexemes. It's free software written using Python 3 in 2020 Wikidata:LexUse.
Wikibase.NET(非推奨)
Wikibase.NET is the api that replaces the now deprecated DotNetDataBot. Api client for the MediaWiki extension Wikibase. They aren't compatible because Wikibase.NET does no longer need the DotNetWikiBot framework.
ダウンロードとインストール
You can download Wikibase.NET from GitHub. Just follow the instructions on that page.
既知の問題点
例
近日公開「しません」...
DotNetDataBot (Deprecated)
インストール
- ダウンロード: DotNetDataBot
設定
After unpacking the package you can see a file called DotNetDataBot.dll and one called DotNetDataBot.xml. The xml document is only for documentation. To use it you have to create a new refer in your project. Then you can write using DotNetDataBot;
to import the framework.
ログイン
To login you have to create a new Site
object with the url of the wiki, your bot's username and its password.
Extended content |
---|
C# using DotNetDataBot;
public static void Main()
{
Site wikidata = new Site("http://www.wikidata.org", "User", "Password");
}
|
例1: ウィキページで使用しているIDの取得
You can access the id of an item by searching for using the site and the title of the connected page.
Extended content |
---|
C# using DotNetDataBot;
public static void Main()
{
Site site = new Site("http://www.wikidata.org", "User", "Password");
Item item = new Item(site);
if (item.itemExists("it", "George Lucas")) // Check if exist on Wikidata
{
Console.Write("Q" + item.GetIdBySitelink("it", "George Lucas"));
}
else
{
Console.Write("Doesn't exist");
}
}
|
例2: ウィキ間リンクの取得
You can get the interwiki links of an item by loading the content and accessing the links
field of the object.
Extended content |
---|
C# using DotNetDataBot;
public static void Main()
{
Site site = new Site("http://www.wikidata.org", "User", "Password");
Item item = new Item(site);
item.id = item.GetIdBySitelink("it", "George Lucas");
item.Load();
foreach(KeyValuePair<string, string> link in item.links)
{
Console.Write(link.Key); // lang (eg. en or it)
Console.Write(link.Value); // page (eg. George_Lucas)
}
}
|
例3: 説明の設置
To set a description, you must call the setDescription
function.
Extended content |
---|
C# using DotNetDataBot;
public static void Main()
{
Site site = new Site("http://www.wikidata.org", "User", "Password");
Item item = new Item(site, "Q4115189");
item.Load();
if (item.descriptions.ContainsKey("it")) // if alredy exist description in italian
{
// Nothing to do
}
else
{
item.setDescription("it", "description in italian", "Bot: Add italian description");
}
}
|
例4: ラベルの設置
It works the same way for setting a label. Just call setLabel
.
Extended content |
---|
C# using DotNetDataBot;
public static void Main()
{
Site site = new Site("http://www.wikidata.org", "User", "Password");
Item item = new Item(site, "Q4115189");
item.Load();
if (item.labels.ContainsKey("it")) // if alredy exist label in italian
{
// Nothing to do
}
else
{
item.setLabel("it", "label in italian", "Bot: Add italian label");
}
}
|
Example 5: Get interwiki links for 100 pages
This feature is not supported. Just iterate over the list.
PHPウィキベースAPI
This is an api client for Wikibase written in PHP. It can be downloaded from here.
例1:基本的な例
Take a look at the source comments to understand how it works.
Extended content |
---|
<?php
/**
* Basic example for the use of the libary with some small edits
*/
require_once( __DIR__ . "/vendor/autoload.php" );
// Creates some useful objects and logs into the api
$api = new \Mediawiki\Api\MediawikiApi( "http://www.wikidata.org/w/api.php" );
$api->login( new \Mediawiki\Api\ApiUser( 'username', 'password' ) );
$dataValueClasses = array(
'unknown' => 'DataValues\UnknownValue',
'string' => 'DataValues\StringValue',
);
$wikidata = new \Wikibase\Api\WikibaseFactory(
$api,
new DataValues\Deserializers\DataValueDeserializer( $dataValueClasses ),
new DataValues\Serializers\DataValueSerializer()
);
// Gets the current revision for item Q777
$revision = $wikidata->newRevisionGetter()->getFromId( 'Q777' );
$item = $revision->getContent()->getData();
// Outputs the current sitelink for enwiki
var_dump( $item->getSiteLink( 'enwiki' ) );
// Sets the de description to 'Foobar'
$item->getFingerprint()->setDescription( 'de', 'Foobar' );
// Saves the item
$wikidata->newRevisionSaver()->save( $revision );
//Log out
$api->logout();
|
例2: 主張の作成
Take a look at the source comments to understand how it works.
Extended content |
---|
<?php
/**
* Basic example for the use of the library with some small edits.
*/
require_once( __DIR__ . "/vendor/autoload.php" );
// Creates some useful objects and logs into the api
$api = new \Mediawiki\Api\MediawikiApi( "https://www.wikidata.org/w/api.php" );
$api->login( new \Mediawiki\Api\ApiUser( 'username', 'password' ) );
$dataValueClasses = array(
'unknown' => 'DataValues\UnknownValue',
'string' => 'DataValues\StringValue',
);
$services = new \Wikibase\Api\WikibaseFactory(
$api,
new DataValues\Deserializers\DataValueDeserializer( $dataValueClasses ),
new DataValues\Serializers\DataValueSerializer()
);
$revision = $services->newRevisionGetter()->getFromId( 'Q777' );
$item = $revision->getContent()->getData();
$statementList = $item->getStatements();
if( $statementList->getByPropertyId( \Wikibase\DataModel\Entity\PropertyId::newFromNumber( 1320 ) )->isEmpty() ) {
$services->newStatementCreator()->create(
new \Wikibase\DataModel\Snak\PropertyValueSnak(
\Wikibase\DataModel\Entity\PropertyId::newFromNumber( 1320 ),
new \DataValues\StringValue( 'New String Value' )
),
'Q777'
);
}
// Log out
$api->logout();
|
VBot (no updates since 2017)
Framework for Wikidata and Wikipedia. Read and write on Wikidata and other Wikimedia project and have a useful list generator to generate list of Wikipedia page and Wikidata entity. Can read also JSON dump of Wikidata.
概要
Bot to read and edit Wikidata and Wikipedia.
- License: CC0 1.0
- Language C#
- Can read and write entities with all datatype on Wikidata
- Can read and write pages on all Wiki project
- Can read parameter from template on wiki pages
- Can read JSON dump
- Can create lists using:
- Wikidata query
- Catscan 2
- Quick intersection
- What Links Here on Wikidata
- Tested with Visual Studio Express 2013 for Windows Desktop.
- Is necessary to have Newtonsoft.Json. You can install it with NuGet inside Visual Studio
- Is necessary to add manually a reference to System.Web for "HttpUtility.UrlEncode"
ダウンロード
The framework can be downloaded from GitHub here.
説明
- Wiki (部分)
- User talk:ValterVB :)
例1
Update en label for all items with instance of (P31): short film (Q24862) that have director (P57) and that have publication date (P577) in 1908. (Use of Wikidata query)
Extended content |
---|
private void CompleteExample()
{
//Wikidata query
string strWDQ = "CLAIM[31:24862] AND CLAIM[57] AND BETWEEN[577,+00000001908-00-00T00:00:00Z,+00000001908-12-31T00:00:00Z]";
ListGenerator lg = new ListGenerator();
List<string> chunks = lg.WDQ(strWDQ, 50);
//Connection to Wikipedia
WikimediaAPI WP = new WikimediaAPI("https://it.wikipedia.org", User, Password);
Pages PageList = new Pages();
//Connection to Wikidata
WikimediaAPI WD = new WikimediaAPI("https://www.wikidata.org", User, Password);
Entities EntityList = new Entities();
Dictionary<string, string> Labels = new Dictionary<string, string>();
foreach (string list in chunks)
{
// Load all entity of the chunk
string strJson = WD.LoadWD(list);
EntityList = new Entities();
EntityList = JsonConvert.DeserializeObject<Entities>(strJson, new DatavalueConverter());
foreach (KeyValuePair<string, Entity> entity in EntityList.entities)
{
if (entity.Value.sitelinks.ContainsKey("itwiki"))
{
// Load Wikipage
string Pages = WP.LoadWP(entity.Value.sitelinks["itwiki"].title);
PageList = JsonConvert.DeserializeObject<Pages>(Pages, new DatavalueConverter());
//Director from template
string director = Utility.GetTemplateParameter(PageList.query.FirstPageText, "film","Regista").Replace("[","").Replace("]", "");
Labels = new Dictionary<string, string>();
if (director=="")
{
Labels.Add("en", "1908 short movie");
}
else
{
Labels.Add("en", "1908 short movie directed by " + director);
}
// Update Wikidata
WD.EditEntity(entity.Value.id, null, Labels, null, null, null, "BOT: Update en label");
}
}
}
}
|
LexData (Python; for Lexicographical data)
LexData is an easy to use python libary to create and edit Lexemes, Senses and Forms.
ヒント
The documentation of LexData is still a bit lacking so look at existing implementations in MachtSinn or Wikdata Lexeme Forms for ideas how to use it.
If you only want to add statements to Lexemes (not forms or senses) WikibaseIntegrator might be a better choice, as it is more versatile and support a lot of data types.
インストール
You can install LexData via pip:
$ pip install LexData
ログイン
For all operations you need a WikidataSession
. You can create it with your credentials, a bot password or an Edit Token (for example to edit via OAUTH):
Extended content |
---|
repo = LexData.WikidataSession("YourUsername", "YourPassword")
|
語彙素の取得
You can open existing Lexemes and read their content.
Extended content |
---|
L2 = LexData.Lexeme(repo, "L2")
print(L2.claims)
print(L2.forms)
print(L2.senses)
sense1 = L2.senses[0]
print(sense1.claims)
|
Searching and creating Lexemes
If you don't know the L-Id of a lexeme you can search for it. And if it doesn't exist you can create it.
Extended content |
---|
# Find an existing Lexeme by lemma, language and grammatical form
L2 = LexData.search_lexemes(repo, "first", en, "Q1084")
# Create a new Lexeme
L2 = LexData.create_lexeme(repo, "first", en, "Q1084")
# Find or create a Lexeme
L2 = LexData.get_or_create_lexeme(repo, "first", en, "Q1084")
|
情報の追加
You can easily create forms or senses, with or without additional claims:
Extended content |
---|
if len(L2.forms) == 0:
L2.createForm("firsts", ["Q146786"])
if len(L2.senses) == 0:
L2.createSense(
{
"en": "Element in an ordered list which comes before all others according to the ordering",
"de": "einer Ordnung folgend das Element vor allen anderen",
},
claims={"P5137": ["Q19269277"]},
)
|
ウィキデータの API を直接使用する
The other sections describe how to use bot frameworks to access and update Wikidata information.
You can also directly interact with the Wikibase API that Wikidata provides.
You need to do this if you're developing your own framework or if you need to do something that a framework doesn't support.
The documentation for the Wikibase API can be found at mediawiki.org. You can also play around with it at Special:ApiSandbox, try action=wbgetentities
.
Wikibase provides its API as a set of modules for MediaWiki's "action" API. You access this by making HTTP requests to /w/api.php
.
The default response format is JSON.
So for your language of choice, you only need a library to perform HTTP requests and a JSON or XML library to parse the responses.
例1 : Qナンバーの取得
This example gets the item Q number for the English Wikipedia article about Andromeda Galaxy. The Wikibase API's main "workhorse" module action=wbgetentities
provides this information. The HTTP request (using jsonfm
format for human-readable JSON output) is simply
Try following the link. This requests no additional information about the entity; remove &props=
from the URL to see much more information about it.
See the generated help for wbgetentities
for more parameters you can specify.
Python
Extended content |
---|
#!/usr/bin/python3
from requests import get
def get_qnumber(wikiarticle, wikisite):
resp = get('https://www.wikidata.org/w/api.php', {
'action': 'wbgetentities',
'titles': wikiarticle,
'sites': wikisite,
'props': '',
'format': 'json'
}).json()
return list(resp['entities'])[0]
print(get_qnumber(wikiarticle="Andromeda Galaxy", wikisite="enwiki"))
|
The output is:
Q2469
Example 2: Get list of items without particular interwiki
...please contribute if you know how...
関連項目
- mw:Wikidata Toolkit Java framework
- Wikidata:Bots