Apri il menu principale

Interrogazione via AJAXModifica

Per invocare una API via AJAX ottenendo un oggetto JSON, esempio:

oggetto=JSON.parse($.ajax({
    url:"/w/api.php?action=query&indexpageids&prop=revisions&rvprop=content&format=json&titles=Pagina:Manzoni.djvu/135",
    async: false
    }).responseText);

Questo oggetto ha una struttura complessa. Il dato preliminare da estrarre è l'id pagina che si ottiene:

id=oggetto.query.pageids[0];

Ottenuto l'id, allora:

  • oggetto.query.pages[id].revisions[0]["*"] fornisce il codice della pagina in formato testo;
  • oggetto.query.pages[id].ns fornisce il namespace (numero)

Un'altra query sulla stessa pagina:

oggetto=JSON.parse($.ajax({
    url:"/w/api.php?action=query&prop=info&indexpageids&format=json&titles=Pagina:Manzoni.djvu/135",
    async: false
    }).responseText);

Ricavato l'id con la stessa istruzione:

id=oggetto.query.pageids[0];

l'oggetto JSON contiene parecchi dati:

  • oggetto.query.pages[id].lastrevid contiene l'id dell'ultima revisione;
  • oggetto.query.pages[id].length la lunghezza in caratteri;
  • oggetto.query.pages[id].ns il numero namespace;
  • oggetto.query.pages[id].title il titolo;
  • oggetto.query.pages[id].touched la data/ora dell'ultima modifica.
Riferimenti
  • doc generale (quasi illeggibile);
  • API:Main page e pagine correlate, scritte in liguaggio umano ma solo con pochissimi esempi base.

BacklinksModifica

Questa query:

puntanoQui=JSON.parse($.ajax({url:"/w/api.php?action=query&format=json&list=backlinks&bltitle=Pagina:Manzoni.djvu/135",async:false}).responseText);

restituisce un oggetto molto più semplice contenente l'analogo di "Puntano qui".

In particolare:

  • lista=puntanoQui.query.backlinks; è una semplice lista di piccoli oggetti pagina con i seguenti elementi:
  1. ns che è il numero del namespace;
  2. id è l'id;
  3. title è il titolo completo di namespace.

Quindi:

  • lista[0].title fornisce il titolo;
  • lista[0].id fornisce l'id;
  • e così per i vari elementi della lista.

Per Pagina:Manzoni.djvu/135, lista "stringifycata" via JSON è:

  • [{"pageid":88265,"ns":110,"title":"Indice:Manzoni.djvu"},{"pageid":88768,"ns":0,"title":"Alessandro Manzoni - studio biografico/Capitolo XIV"}]

Filtrando su ns, è facile ottenere la lista delle pagine in ns0 in cui una pagina Pagina è transclusa. Come volevasi ottenere.

Ottenere l'html della pagina correnteModifica

Per ottenere l'html della pagina corrente (puro html dal parsing del codice wiki) meglio usare index:

html=$.ajax({url:"http://it.wikisource.org/w/index.php?action=render&title=Pagina:Manzoni.djvu/135",async:false}).responseText;

La cosa può essere utile per leggere i dati che derivano dall'elaborazione della pagina; es. trovare il SAL delle pagine transcluse, mentre si è in edit. Il problema è esattamente speculare a quello di disporre del codice wiki in modalità view. Esempio: entrando in modifica di una pagina ns0 da transclusione, si può ottenere l'elenco dei SAL pagina e quindi il SAL "da transclusione"; ma si può anche ottenere la lista specifica dei "link rossi", o i dati semantizzati via transclusione.

Con un altro parametro, action=raw, si ottiene "al volo" il wikitesto della pagina (viene restituito il testo puro e semplice, e non un oggetto complesso come quello che si ottiene via API):

html=$.ajax({url:"http://it.wikisource.org/w/index.php?action=raw&title=Pagina:Manzoni.djvu/135",async:false}).responseText;

UltimeModificheModifica

Utilissimo tool per verificare il proprio codice è: Sandbox API, esso ci permette di verificare che la nostra query funzioni a dovere.

Le Ultime modifiche si possono ottenere attraverso questo codice: api.php?action=query&list=recentchanges.

La sintassi da utilizzare è spiegata qui anche se le cose più utili da sapere sono:

  • rcstart: questo parametro ci permette di stabilire la data di partenza delle modifiche che vogliamo vedere.
  • rcend: questa è la data finale.
  • rcnamespace: per impostare un namespace specifico (identificato da un numero), se non specifichiamo nulla, viene sottinteso che si vogliano vedere tutti i namespace
  • rcprop: grazie a questo parametro possiamo limitare le caratteristiche delle modifiche. Possiamo richiedere solo il titolo, oppure l'id o altro (per la documentazione completa, visitare il link precedente)
  • rctype:
  • rcshow:


Parsing pagina indiceModifica

// Accetta il nome di una pagina Indice
// Restituisce un oggetto di  oggetti con prima chiave numero pagina djvu e 
// attributi title, quality, label per l'oggetto di secondo livello

function obIndex(indice) {
     html=$.ajax({url:"http://it.wikisource.org/w/index.php?action=render&title="+indice,async:false}).responseText;
     t=$(".pagineDellEdizione a",html);
     l={};
     for (i=0;i<t.length;i+=1) {
         tt=t.eq(i);
         ll={};
         ll.title=find_stringa(tt.attr("title"),"/"," ",0);
         ll.quality=tt.attr("class").replace("quality","");
         ll.label=(isNaN(tt.text()*1)) ? tt.text() : tt.text()*1
         l[i]=ll
     }
return l;
}


function contaSal(oggettoIndice) {
var n={"new":0,"0":0,"1":0,"2":0,"3":0,"4":0};
for (i in oggettoIndice) {
   n[oggettoIndice[i].quality]+=1;
   }
return n;
}

Query API interprogettoModifica

A seguito di discussione su wikitech-l ricevo questo suggerimento per aggirare la "same origin policy" di Ajax ed eseguire query interprogetto da Brion Vibber:

Luckily, if you're using jQuery much of the low-level stuff can be taken
care of for you. Something like this should work for API calls,
automatically using the callback behind the scenes:

$.ajax({
  url: 'https://commons.wikimedia.org/w/api.php',
  data: {
    format: 'json',
    // ... various settings ...
   },
   dataType: 'jsonp' // this is the important one!
}).done(function(data) {
  // do some work here
  alert(JSON.stringify(data));
});

You can look up the various parameters for different queries in the online
help at https://commons.wikimedia.org/w/api.php and/or playing with the API
sandbox at https://commons.wikimedia.org/wiki/Special:ApiSandbox

Proviamo....

Lanciando da console:

rawCode='';
$.ajax({
  url: 'https://commons.wikimedia.org/w/api.php',
  data: {
    format: 'json',
    action: 'query',
    titles: 'Creator:Francesco Gonin',
    prop: 'revisions',
    rvlimit: '1',
    rvprop: 'content'
   },
   dataType: 'jsonp' // this is the important one!
}).done(function(data) {
  // do some work here
  rawCode=data; // rawCode=JSON.stringify(data);
});

ottengo effettivamente l'oggetto JSON relativo all'ultima revisione della pagina Creator:Francesco Gonin su Commons.

Per maneggiare questo oggetto, estraggo la lista degli ids (in questo caso, uno):

l=[];
for (i in rawCode.query.pages) {l.push(i);}

dopodichè posso accedere, nell'oggetto, a qualsiasi elemento di ognuna delle pagine, qui ad esempio accedo al testo raw dell'ultima revisione:

testo=rawCode.query.pages[l[0]].revisions[0]["*"]

e dandolo in pasto a parseTemplate("Creator",testo) ne faccio quello che voglio.

Hurrà.}}

Ajax vs wikidataModifica

primo test (Q1064 è Alessandro Manzoni)(il wikidata id sta in wgWikibaseItemId se esiste "elemento dati")

rawCode='';
$.ajax({
  url: 'https://www.wikidata.org/w/api.php',
  data: {
    format: 'json',
    action: 'wbgetentities',
    ids: 'Q1064',
    props:"labels|descriptions|sitelinks|claims", languages:"it"
  
   },
   dataType: 'jsonp' // this is the important one!
}).done(function(data) {
  // do some work here
  rawCode=data; 
});

getAny()Modifica

Adesso si fa sul serio.

Sia data la funzione, attiva per tutti (sta in Common.js):

function getAny(parametri) {
	$.ajax(parametri.ajax).done(function (data) {
		parametri.callback( parametri, data);
	});
}

Questa funzione è onnipotente e modulare. Si tratta di una interrogazione AJAX asincrona composta da due elementi:

  1. parte "query": cosa voglio ottenere, $.ajax(parametri.ajax); si ottiene l'oggetto JSON data;
  2. parte "do": cosa voglio fare di ciò che ho ottenuto, parametri.callback( parametri, data).

Tutto ciò che serve per attivare la funzione è una corretta costruzione del parametro parametri, un oggetto js di struttura costante, con alcuni elementi variabili; alcuni elementi sono necessari alla parte query, altri alla parte do, altri ad entrambe.

Una struttura comune di parametri è la seguente:

parametri = {
		sito: sito,        
		titolo: titolo,
		        ajax: {
			url: 'https://' + sito + '/w/api.php',
			async: false, // NON MODIFICARE
			data: {
				format: 'json',
				action: 'parse',
				page: titolo,          
				prop: 'text'
			},
			dataType: 'jsonp' // NON MODIFICARE
		},
                callback: callback1, // questa funzione viene eseguita su data tenendo anche conto di parametri
	}

Partiamo dal fondo, parametro callback. Le funzione asincrone "non restituiscono niente". C'è quindi il problema di recuperare i dati data che sono "seppelliti" dentro la funzione. Per estrarre dati, occorre "fare qualcosa" con la funzione callback. La cosa più semplice da fare è caricare data in un elemento HTML "contenitore" con il metodo jQuery .data().

Qui su wikisource è predisposto un "elemento html contenitore" <div class="ourDiv"></div> in cui un dato di tipo generico, dati, può essere stabilmente memorizzato con l'istruzione:

$(".ourDiv").data("risultato",dati);

Un esempio di caricamento e recupero copiaincollando dalla console js di Chrome:

> $(".ourDiv").data("test","dati di prova")
 <div class=​"ourDiv" style=​"display:​none;​">​</div>​
> $(".ourDiv").data("test")
"dati di prova"

La più semplice istruzione callback che esegue qualcosa di utile è la seguente; non fa niente altro che ficcare data tal quale nella variabile datiAJAX di .ourDiv:

function callbackBase(data,parametri) {$(".ourDiv").data("datiAJAX",data);} 

E' utile sia per prove da console (esempio, per fare l'autopsia dell'oggetto json ricavato dall'interrogazione AJAX), che per lavori in cui si desidera riutilizzare, durante il "tempo di vita della pagina corrente", i contenuti di data.

Beninteso: le funzioni qui sopra sono "onnipotenti" anche nel senso che funzionano da qualsiasi progetto wiki che abbia jQuery attivo. Nel caso che vi siano dubbi sul fatto che esista una div class="ourDiv" basta usare questo codice al posto del precedente:

function callbackBase(data,parametri) {
   if ($(".ourDiv").length==0) $("body").append($('<div class="ourDiv"></div>')); 
   $(".ourDiv").data("datiAJAX",data);} 

Nuova versione semplificataModifica

getIwPage=function (title, site, query) {
  if (query==undefined) query="text";
  // $("#spinnerIcon").css("display","inline");
  if (query=="html" || query==undefined) data= {format: 'json',action: 'parse',page: title,prop: 'text'};
  if (query=="text") data= {format: 'json',action: 'query',titles: title,   prop: 'revisions',rvlimit: '1',rvprop: 'content'};
  $.ajax({
  url: 'https://'+site+'/w/api.php',
  async:false,
  data:data,
   dataType: 'jsonp' // this is the important one!
}).done(function (data) {
 $("body").data("outputAjax",data);
 if (query=="text") {
     if (data.query.pages[-1]==undefined) {
         l=[]; 
         for (i in data.query.pages) {l.push(i);}; 
         bareData=data.query.pages[l[0]].revisions[0]["*"]; 
     }
     else {
     {
         bareData="Pagina non esistente";
     }
}
 if (query=="html") {
     if (data.error == undefined ) {

         bareData=data.parse.text["*"];
     }
     else
         bareData="Pagina non esistente";
     }

  }

  
 
 $("body").data("bareData",bareData);
 
  //$("#spinnerIcon").css("display","none");
}
);
}
title
titolo della pagina
site
sito wiki (es: it.wikisource.org)
query
dati richiesti, opzionale ("html" | "text", default "text")
output dei dati
  1. in $("body").data("outputAjax") risultato della query Ajax
  2. in $("body").data("bareData") il risultato "nudo"
    1. se la pagina esiste: testo o html della pagina
    2. se la pagina non esiste: "Pagina non esistente"

API per UltimeModificheModifica

oggetto=JSON.parse($.ajax({
    url:"/w/api.php?action=query&list=recentchanges&rcprop=title|ids|sizes|flags|user|timestamp&rclimit=500&format=json",
    async: false
    }).responseText);

Restituisce le ultime 500 modifiche in formato json (i parametri rcprop possono essere adattati)

  • (in studio)

getJSONModifica

Esempio su en.wikisource:

risultato=""
$.getJSON("https://en.wikisource.org/w/api.php?action=query&prop=contributors&titles=Main_Page&format=json&callback=?", function(data) {risultato=data})

Esempio su IA:

risultato=""
$.getJSON("https://archive.org/details/image10TeatroOpal&output=json&callback=?", function(data) {risultato=data})

Richiesta metadati da IA con JSONPModifica

Esempio su IA, ottiene i metadati di un item:

risultato=""
$.ajax({
   url: 'https://archive.org/metadata/SpaccioDeLaBestiaTrionfante',
   dataType: 'jsonp' 
}).done(function (data) {risultato=data;} )

Per ottenere metadati selezionati vedi http://blog.archive.org/2013/07/04/metadata-api/

AJAX server sideModifica

You can get a look at Utilisateur:Phe/Scripts/credits.py for one way to implement the server side. This file must be located as public_html/cgi-bin/credits with 0755 permission, a typical call is [5], a real call from javascript will use format=json (jsonfm return the json data as text) and a callback=your_javascript_function_to_treat_answer. The interesting part of the script start at def query_params(environ):... — Phe 21 mai 2013 à 09:49 (UTC)

Funzione di scorrimento di pagine per ricerca ancora (su Cantoni)Modifica

function x(ini,fin) {
	var base="Pagina:Cantoni - Trattato completo di agricoltura, 1855, I.djvu/"; 
	var l={}; 
	var sezioni=[];
	var ancora=""; 
	var testo="";
	for (i=ini;i<fin;i+=1) {
		testo=$.ajax({url:"//it.wikisource.org/w/index.php?action=raw&title="+base+i,async:false}).responseText; 
		sezioni=produciLista(testo,"{{§|","}}",1);
		for (j=0;j<sezioni.length;j+=1) {
		/*{{§|s379|§ 379.}}*/ 
			ancora=sezioni[j].match(/\|(s\d+)\|/)[1];
			l[ancora]=i;
            }
	console.log(i);
	}
	return l;
}

Lettura e memorizzazione di item wikidata correnteModifica

@CandaluaDa una pagina connessa a un elemento wikidata:

function wikidataItem() {
var id=$("#t-wikibase a").attr("href").match(/Q\d+/);
if (id===null) return; else id=id[0];
$.ajax({
  url: 'https://www.wikidata.org/w/api.php',
  data: {
    format: 'json', 
    action: 'wbgetentities',
    ids: id,
    props: 'claims',
    languages: 'it'
   },
   dataType: 'jsonp' 
}).done(function(data) {
  // do some work here
  
  mw.wikidataItem=data.entities[id].claims;
  localStorage.wikidataItem=JSON.stringify(mw.wikidataItem);
});
}

in mw.wikidataItem caricato un oggetto semplificato che ha come keys i claims dell'item e loro sottocampi; lo stesso oggetto, stringificato in JSON, viene caricato in modo persistente in localStorage.wikidataItem.

Passando l'output alla funzione seguente, si scorrono i valori e si produce la lista degli id delle proprietà e di tutti i loro valori che sono costituiti da un item:

function getNestedItems(item) {
   var l={};
   for (pr in item) {
   property=item[pr];
   for (i in property) { 
	prop=property[i];
   	// console.log(prop);var entity="";
   	if (prop.mainsnak.datavalue.value["entity-type"]==="item") {
		id=prop.mainsnak.datavalue["numeric-id"];
		entity="Q"+prop.mainsnak.datavalue.value["numeric-id"];
		}
    	if (prop.mainsnak.datavalue.value["entity-type"]==="property") {
		id=prop.mainsnak.datavalue["numeric-id"];
		entity="P"+prop.mainsnak.datavalue.value["numeric-id"];
		}
	if (entity!=="") l[entity]=true;
    }
    }
    var properties=Object.keys(item);
	for (i in properties) {l[properties[i]=true;}
    return Object.keys(l);
}

Dopo join, la lista (se il numero di elementi è inferiore a 50) può essere passato a una richiesta wbgetentities con props=labels, language=it, ids=[join("|") della lista] e siottiene un oggetto avvastanza semplice che contiene il dizionario items-labels.

Edit di una paginaModifica

function pageSave(titolo,testo,commento) {
		

		$.ajax({
         	url: mw.util.wikiScript( 'api' ),
        	data: {
            	format: 'json',
            	action: 'edit',
            	title: titolo,
            	summary: commento,
            	text: testo,
            	token: mw.user.tokens.values.editToken
        	},
        	dataType: 'json',
        	type: 'POST',
        	success: function( data ) {
        		if ( data && data.edit && data.edit.result == 'Success' ) {
					console.log("OK");
					
            		} else if ( data && data.error ) {
                		alert( 'Error: API returned error code "' + data.error.code + '": ' + data.error.info );
            			} else {
                			alert( 'Error: Unknown result from API.' );
        					 }
        		},
        		error: function( xhr ) {
        		 alert( 'Error: Request failed.' );
				}
    	});
	}

Caricamento rawcode interprogetto di una pagina Pagina qualsiasiModifica

getRawCode=function (title, site) {
        if (site===undefined) site=mw.config.get("wgServer");
        var data= {format: 'json',action: 'query',titles: title,   prop: 'revisions',rvlimit: '1',rvprop: 'content'};
        var rawCode="";
        $.ajax({
                url: site+'/w/api.php',
                async:false,
                data:data,
                dataType: 'jsonp',
               

        }).done(function (data) {
                if (data.query.pages[-1]===undefined) {
                        l=[]; 
                        for (var i in data.query.pages) {
                                l.push(i);
                        } 
                        rawCode=data.query.pages[l[0]].revisions[0]["*"]; 
                        localStorage.rawCode=rawCode;
						var r=/pagequality level="(\d)" user="([^"]+)"/ ;
						var m=[]; localStorage.pageLevel="";localStorage.pageUser="";localStorage.validable=false;
						if (r.test(rawCode)) {
							m=rawCode.match(r);
							localStorage.pageLevel=m[1];
							localStorage.pageUser=m[2]; 
                                                        if (localStorage.pageLevel==="3" && localStorage.pageUser!==mw.config.get("wgUserName")) localStorage.validable=true;
						}
                } else {
                        alert("Pagina non esistente");
                }
                
        });
};


Caricamento rawcode interprogetto di una pagina generica qualsiasiModifica

getRawCode=function (title, site) {
        if (site===undefined) site=mw.config.get("wgServer");
        var data= {format: 'json',action: 'query',titles: title,   prop: 'revisions',rvlimit: '1',rvprop: 'content'};
        var rawCode="";
        $.ajax({
                url: site+'/w/api.php',
                async:false,
                data:data,
                dataType: 'jsonp',
               

        }).done(function (data) {
                if (data.query.pages[-1]===undefined) {
                        l=[]; 
                        for (var i in data.query.pages) {
                                l.push(i);
                        } 
                        rawCode=data.query.pages[l[0]].revisions[0]["*"]; 
                        localStorage.rawCode=rawCode;
						
                } else {
                        alert("Pagina non esistente");
                }
                
        });
};