问题描述
这个问题的续篇:Live statistics chess960 from chess.com?
所以假设我去喜欢
https://api.chess.com/pub/player/gmwso/games/2020/12
或
https://api.chess.com/pub/player/gmwso/games/2020/12/pgn
会有一堆东西说
[UTCDate "2018.01.03"]
[WhiteElo "2706"]
[BlackElo "2940"]
如何将这些数据放入电子表格中,例如第 1 列是所有日期,第 2 列是相应的白色 elo,第 3 列黑色 elo,col4 白色用户名和 col5 黑色用户名?
更新 2:现已修复。请参阅“json”与“预制”。哇。
更新 1:Mike Steelson 似乎有一个答案 here,其中代码为
=arrayformula( regexextract(split( substitute(substitute(substitute(getDataJSON(A1;"/games";"/pgn");"[";"");"]";"");"""";"") ;char(10));"\s.*") )
这里有一个例子
https://docs.google.com/spreadsheets/d/1MX1o5qdy0K3gTMzbimUV3SmFf-0XPCSJ8Vz4IjI-8Ak/copy
仅在 chess960 的情况下似乎存在问题。考虑例如 this player:用玩家的用户名替换 'gmwso' 会产生一个奇怪的输出。我想混合 chess960 和国际象棋的输出会更混乱。
解决方法
试试
=arrayformula( regexextract(split( substitute(substitute(substitute(getDataJSON(A1;"/games";"/pgn");"[";"");"]";"");"""";"") ;char(10));"\s.*") )
用这段代码提取json
let resultat = [];
function getDataJSON(url,tableau,xpath){
try{
if (url.match(/http(s)?:\/\/?/g)){var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())}
else{var data = JSON.parse(url)}
var json = eval('data'+tableau.replace(/\//gm,"\."))
if (typeof xpath == 'object'){var liste = xpath.join().split(",")} else {var liste = xpath.split("|")}
if (json.length){json.forEach(function(elem){getData(elem,liste)})} else {getData(json,liste)}
return resultat
}
catch(e) {
return ('Pas de résultat - vérifier l\'url et les paramètres !');
}
}
function getData(elem,liste){
var prov=[]
liste.forEach(function(chemin){
var t=chemin.split('/');
var obj=elem;
for (var i=1;i<t.length;i++){obj=obj.item(t[i])}
if(typeof obj=='object'){prov.push('['+obj+']')}else{prov.push(obj)}
})
resultat.push(prov)
}
Object.prototype.item=function(i){return this[i]};
https://docs.google.com/spreadsheets/d/1MX1o5qdy0K3gTMzbimUV3SmFf-0XPCSJ8Vz4IjI-8Ak/copy
,另一种更简单、更集成的解析 PGN 文件的方法
/**
* Parse a PGN file.
*
* @param {range} url url
* @param {range} xpath data to be fetched
* @param {boolean} sequence if true sequence will be fetched
* @customfunction
*/
function readPGN(url,xpath,sequence) {
var result=[]
var reponse = UrlFetchApp.fetch(url);
var json = reponse.getContentText();
var data = JSON.parse(json);
if (typeof xpath == 'object'){var liste = xpath.join().split(",")} else {var liste = xpath.split("|")}
for (var i=0; i<data.games.length; i++) {
var prov=[]
var parts = data.games[i].pgn.split(String.fromCharCode(10,10))
var pparts = parts[0].split(String.fromCharCode(10))
for (var x=0; x<pparts.length; x++){
pparts[x]=pparts[x].replace('[','"').replace(']','').replace(' "','":"') // "key":"value"
}
var donnees = JSON.parse('{'+pparts.join(',')+'}') // mise au format json
liste.forEach(function(chemin){
prov.push(donnees.item(chemin))
})
if (sequence){prov.push(parts[1])}
result.push(prov)
}
return result
}
Object.prototype.item=function(i){return this[i]};
https://docs.google.com/spreadsheets/d/1asiDRDusHYSDXK0c8gR_GuMIC1Nh0GNXiBpYctrLLlA/copy
,PGN 文件为 https://api.chess.com/pub/player/gmwso/games/2020/12/pgn
function readPGNdirect(url,sequence) {
var result=[]
if (typeof xpath == 'object'){var liste = xpath.join().split(",")} else {var liste = xpath.split("|")}
var data = UrlFetchApp.fetch(url).getContentText().split(String.fromCharCode(10,10,10))
for (var i=0; i<data.length; i++) {
var prov=[]
var parts = data[i].split(String.fromCharCode(10,')+'}') // mise au format json
liste.forEach(function(chemin){
prov.push(donnees.item(chemin))
})
if (sequence){prov.push(parts[1])}
result.push(prov)
}
return result
}
Object.prototype.item=function(i){return this[i]};
工作表“pgn 文件”https://docs.google.com/spreadsheets/d/1asiDRDusHYSDXK0c8gR_GuMIC1Nh0GNXiBpYctrLLlA/copy
,这是完整年份的解决方案
// Mike Steelson
function histo(xpath,depuis,jusque) {
var urlbase = 'https://api.chess.com/pub/player/gmwso/games/YYYY/MM/pgn'
if (typeof xpath == 'object'){var liste = xpath.join().split(",")} else {var liste = xpath.split("|")}
var status = []
var result=[]
var sequence = true
for (var annee=depuis; annee<=jusque; annee++){
for (var mois=1;mois<=12;mois++){
var url = (urlbase.replace('YYYY',annee).replace('MM',(mois<10?'0':'')+mois))
status.push([url,getStatusCode(url),annee,mois])
}
}
status.forEach(function(site){
if(site[1]==200){
var url = site[0]
var response = UrlFetchApp.fetch(url,{'muteHttpExceptions': true});
if (response==''){
result.push('no data for '+site[2]+'/'+(site[3]<10?'0':'')+site[3])
}else{
var data = response.getContentText().split(String.fromCharCode(10,10))
for (var i=0; i<data.length; i++) {
var prov=[]
var parts = data[i].split(String.fromCharCode(10,10))
var pparts = parts[0].split(String.fromCharCode(10))
for (var x=0; x<pparts.length; x++){
pparts[x]=pparts[x].replace('[','":"') // "key":"value"
}
var donnees = JSON.parse('{'+pparts.join(',')+'}') // mise au format json
liste.forEach(function(chemin){
prov.push(donnees.item(chemin))
})
if (sequence){prov.push(parts[1])}
result.push(prov)
}
}
}
})
return result
}
Object.prototype.item=function(i){return this[i]};
function getStatusCode(url){
var options = {
'muteHttpExceptions': true,'followRedirects': false
};
var url_trimmed = url.trim();
var response = UrlFetchApp.fetch(url_trimmed,options);
return response.getResponseCode();
}
https://docs.google.com/spreadsheets/d/1wuMWyrffb386F0da8ShPkANXaDqVVZN5EwWZFT82OrE/copy