Grande Quantité d'appels "IMPORTXML" ? solution(s) alternative(s) ?
Bonjour,
Je dispose d'une liste d'environs 200 liens en colonne "A"
j'ai crée différentes fonction "importxml" sur 3 colonnes différentes.
pour donner qu'un petit exemple
=IMPORTXML(A2,"//*[@class='assetAnnualReturn']/span")
=IMPORTXML(A2,"//*[@class='assetTokenPrice']/span")
=IMPORTXML(A2,"//*[@class='assetHasTenants']/span")
=IMPORTXML(A2,"//*[@class='assetSection8']/span")
avant même d'essayer je suppose que je vais grandement ralentir mon Sheet, et surement atteindre des limitations rapidement..
Que ce soit sous forme de formule, ou intégré dans un script…
Une alternative existe pour faire quelque chose "en masse" ?
Pardon pour le doublon, je suis presque sur d'avoir fait un sujet quasiment similaire, bien que j'ai envie de reprendre proprement ce sujet.
Pour les modérateurs : dans mon exemple c'est un site US et les données sont accessible sans login etc.. ( il me semble qu'on avait eu ce sujet à propos du scrapping )
Malgré tout, si ça vous semble litigieux, je fermerai le sujet sans problème.
ce sujet peut être utile même pour Wikipédia au final
merci !
Bonjour Alex
Pour les modérateurs : dans mon exemple c'est un site US et les données sont accessible sans login etc.. ( il me semble qu'on avait eu ce sujet à propos du scrapping )
Sur le plan du droit : aux États-Unis, la justice estime que les données sont publiques en étant diffusées via Internet et peuvent donc être librement collectées via web scraping.
La limitation la plus importante est que l’on ne peut pas utiliser plus de 50 fonctions import(Xml/Html/Feed) par feuille de calcul. Je ne sais pas si cette limite a changé.
Oui voila c'est ça !
je te donne une fonction personnalisée demain, elle devrait pouvoir fonctionner, il faut que j'affine
Merci :)
À tenter ... adaptation d'une astuce vue sur le net
function importRegex(url, regex1, regex2) {
var output = '';
var fetchedUrl = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
if (fetchedUrl) {
var html = fetchedUrl.getContentText().replace(/(\r\n|\n|\r|\t| )/gm,"");
if (html.length && regex1.length) {
output = html.match(regex1)[1].match(regex2);
}
}
// Grace period to avoid call limit
Utilities.sleep(1000);
return output;
}
avec
=value(importRegex(url,regex1,regex2,case à cocher))
en mettant
url : https://realt.co/product/425-steward-ave-jackson-mi-49201/
regex1 : <li class="assetAnnualReturn">(.*)<\/li>
regex2 : [0-9]+\.[0-9]+%
la case à cocher étant faite pour relancer la fonction si besoin
Bonjour,
okay merci ! ça va me faire une bonne base pour adapter sur mon long listing,
je reviendrais ici après quelques essais :)
bonne journée
Je sais que mon script n'est pas fonctionnel ( les regex ne sont pas bon, il faut que je regarde ), mais je me mets ce pense-bête ici pour travailler dessus en débauchant
l'idée étant de faire la même chose pour tout ce que je veux extraire. l'API ici me permet juste d'avoir tout les liens voulus
logiquement on sera pas mal niveau automatisation ?
function test() {
var url = "https://api.realt.community/v1/token";
var classeur = SpreadsheetApp.getActiveSpreadsheet();
var feuille = classeur.getSheetByName('test');
var cell = feuille.getRange('A2:B');
var response = UrlFetchApp.fetch(url, {
"method": "GET",
"headers": {
"accept":"<*/*>",
"X-AUTH-REALT-TOKEN": "_____ma clé API_____",
"Content-Type": "application/json"
}
});
cellAPI.clearContent();
var output = [];
var json = response.getContentText();
var Data = JSON.parse(json);
for (let i in Data) {
var shortName = Data[i].shortName
var marketplaceLink = Data[i].marketplaceLink
var regExpAssetAnnualReturn = <li class="assetAnnualReturn">(.*)<\/li>
var regExp2 = new RegExp("[0-9]+\.[0-9]+%");
var AssetAnnualReturn =importRegex(marketplaceLink,regExpAssetAnnualReturn,regExp2)
output.push(['=hyperlink("' + marketplaceLink + '","'+ shortName + '")',AssetAnnualReturn]);
}
if (output.length > 0) {
feuilleAPI.getRange(2, 1, output.length, output[0].length).setValues(output);
}
}
function importRegex(url, regex1, regex2) {
var output = '';
var fetchedUrl = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
if (fetchedUrl) {
var html = fetchedUrl.getContentText().replace(/(\r\n|\n|\r|\t| )/gm,"");
if (html.length && regex1.length) {
output = html.match(regex1)[1].match(regex2);
}
}
// Grace period to avoid call limit
Utilities.sleep(1000);
return output;
}
plutôt
var regExpAssetAnnualReturn = '<li class="assetAnnualReturn">(.*)<\/li>'
feuilleAPI
et cellAPI
ne sont pas définis
cela risque de durer longtemps ... 4 à 5 minutes sans doute
Parfait ! cela fonctionne partiellement.
lorsque je veux en faire plusieurs, le script mets trop de temps à s'exécuter... ( sachant que je voulais récupérer 4 data différentes )
je remets le script propre ici
function test() {
var url = "https://api.realt.community/v1/token";
var classeur = SpreadsheetApp.getActiveSpreadsheet();
var feuille = classeur.getSheetByName('test');
var cell = feuille.getRange('A2:D');
var response = UrlFetchApp.fetch(url, {
"method": "GET",
"headers": {
"accept":"<*/*>",
"X-AUTH-REALT-TOKEN": "Ma clé API",
"Content-Type": "application/json"
}
});
cell.clearContent();
var output = [];
var json = response.getContentText();
var Data = JSON.parse(json);
for (let i in Data) {
var shortName = Data[i].shortName
var marketplaceLink = Data[i].marketplaceLink
var regExpAssetAnnualReturn1 = '<li class="assetAnnualReturn">(.*)<\/li>'
var regExpAssetAnnualReturn2 = new RegExp("[0-9]+\.[0-9]+%");
var AssetAnnualReturn = importRegex(marketplaceLink,regExpAssetAnnualReturn1,regExpAssetAnnualReturn2)
var regExpAssetTokenPrice1 = '<li class="assetTokenPrice">(.*)<\/li>'
var regExpAssetTokenPrice2 = new RegExp("[0-9]+\.[0-9]+");
var AssetTokenPrice = importRegex(marketplaceLink,regExpAssetTokenPrice1,regExpAssetTokenPrice2)
output.push(['=hyperlink("' + marketplaceLink + '","'+ shortName + '")',AssetAnnualReturn, AssetTokenPrice]);
}
if (output.length > 0) {
feuille.getRange(2, 1, output.length, output[0].length).setValues(output);
}
}
function importRegex(url, regex1, regex2) {
var output = '';
var fetchedUrl = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
if (fetchedUrl) {
var html = fetchedUrl.getContentText().replace(/(\r\n|\n|\r|\t| )/gm,"");
if (html.length && regex1.length) {
output = html.match(regex1)[1].match(regex2);
}
}
// Grace period to avoid call limit
Utilities.sleep(1000);
return output;
}
Ensuite, il faut que je regarde comment récupérer les autres données proprement !
finalement j'ai juste à mettre une "class" différente ici ?
'<li class=" Class personnalisée ">(.*)<\/li>'
j'ai peur du résultat si jamais je veux importer du texte
( pour ces exemples en particuliers, pour lesquels je peux avoir un texte variable )
=IMPORTXML(A2,"//*[@class='assetHasTenants']/span")
=IMPORTXML(A2,"//*[@class='assetSection8']/span")
merci
Remplace ceci
for (let i in Data) {
var shortName = Data[i].shortName
var marketplaceLink = Data[i].marketplaceLink
var regExpAssetAnnualReturn = '<li class="assetAnnualReturn">(.*)<\/li>'
var regExp2 = new RegExp("[0-9]+\.[0-9]+%");
var AssetAnnualReturn = importRegex(marketplaceLink, regExpAssetAnnualReturn, regExp2)
output.push(['=hyperlink("' + marketplaceLink + '","' + shortName + '")', AssetAnnualReturn]);
}
par
var regExpAssetAnnualReturn = '<li class="assetAnnualReturn">(.*)<\/li>'
var regExpAssetHasTenants = '<li class="assetHasTenants">(.*)<\/li>'
var regExpAssetSection8 = '<li class="assetSection8">(.*)<\/li>'
var regExpPourCent = '<span class="data">([0-9]+\.[0-9]+%)<\/span>';
var regExpText = '<span class="data">([A-Za-z ]+)<\/span>'
for (let i in Data) {
var shortName = Data[i].shortName
var marketplaceLink = Data[i].marketplaceLink
var fetchedUrl = UrlFetchApp.fetch(marketplaceLink, { muteHttpExceptions: true });
if (fetchedUrl) {
var html = fetchedUrl.getContentText().replace(/(\r\n|\n|\r|\t| )/gm, "");
if (html.length) {
var assetAnnualReturn = html.match(regExpAssetAnnualReturn)[1].match(regExpPourCent)[1];
var assetHasTenants = html.match(regExpAssetHasTenants)[1].match(regExpText)[1];
var assetSection8 = html.match(regExpAssetSection8)[1].match(regExpText)[1];
}
}
output.push(['=hyperlink("' + marketplaceLink + '","' + shortName + '")', assetAnnualReturn, assetHasTenants, assetSection8]);
}
et supprime la fonction importRegex
cela devrait durer le même temps !
Modification faite ( et je t'ai repondu en Mp )
Remplace ceci...
function test() {
var url = "https://api.realt.community/v1/token";
var classeur = SpreadsheetApp.getActiveSpreadsheet();
var feuille = classeur.getSheetByName('test');
var cell = feuille.getRange('A2:D');
var response = UrlFetchApp.fetch(url, {
"method": "GET",
"headers": {
"accept":"<*/*>",
"X-AUTH-REALT-TOKEN": " Ma clé API ",
"Content-Type": "application/json"
}
});
cell.clearContent();
var output = [];
var json = response.getContentText();
var Data = JSON.parse(json);
var regExpAssetAnnualReturn = '<li class="assetAnnualReturn">(.*)<\/li>'
var regExpAssetHasTenants = '<li class="assetHasTenants">(.*)<\/li>'
var regExpAssetSection8 = '<li class="assetSection8">(.*)<\/li>'
var regExpPourCent = '<span class="data">([0-9]+\.[0-9]+%)<\/span>';
var regExpText = '<span class="data">([A-Za-z ]+)<\/span>'
for (let i in Data) {
var shortName = Data[i].shortName
var marketplaceLink = Data[i].marketplaceLink
var fetchedUrl = UrlFetchApp.fetch(marketplaceLink, { muteHttpExceptions: true });
if (fetchedUrl) {
var html = fetchedUrl.getContentText().replace(/(\r\n|\n|\r|\t| )/gm, "");
if (html.length) {
var assetAnnualReturn = html.match(regExpAssetAnnualReturn)[1].match(regExpPourCent)[1];
var assetHasTenants = html.match(regExpAssetHasTenants)[1].match(regExpText)[1];
var assetSection8 = html.match(regExpAssetSection8)[1].match(regExpText)[1];
}
}
output.push(['=hyperlink("' + marketplaceLink + '","' + shortName + '")', assetAnnualReturn, assetHasTenants, assetSection8]);
}
if (output.length > 0) {
feuille.getRange(2, 1, output.length, output[0].length).setValues(output);
}
}
il faudrait ajouter une gestion d'erreur car certains sites n'ont pas certaines valeurs
if (fetchedUrl) {
var html = fetchedUrl.getContentText().replace(/(\r\n|\n|\r|\t| )/gm, "");
if (html.length) {
try {
var assetAnnualReturn = html.match(regExpAssetAnnualReturn)[1].match(regExpPourCent)[1];
}
catch (e) {
var assetAnnualReturn = ''
}
try {
var assetHasTenants = html.match(regExpAssetHasTenants)[1].match(regExpText)[1];
}
catch (e) {
var assetHasTenants = ''
}
try {
var assetSection8 = html.match(regExpAssetSection8)[1].match(regExpText)[1];
}
catch (e) {
var assetSection8 = ''
}
}
}
output.push(['=hyperlink("' + marketplaceLink + '","' + shortName + '")', assetAnnualReturn, assetHasTenants, assetSection8]);
}
Merci.
EDIT : suite a mon dernier message dans tes Mp, j'ai compris : il y a parfois que des nombres entiers qui ne sont pas pris en compte !
j'ai voulu essayer une " double-chance" comme ceci :
var regExpPourCent = '<span class="data">([0-9]+\.[0-9]+%)<\/span>'|'<span class="data">([0-9]+%)<\/span>';
mais ça ne fonctionne pas ahha
au fait, j'ai fait trop de zèle
ceci
'<span class="data">([0-9]+\.[0-9]+%)<\/span>'
'<span class="data">([A-Za-z ]+)<\/span>'
peut être remplacé par
'<span class="data">(.*)<\/span>'
tout simplement
je n'ai pas obtenu un bon resultat avec ça
J'ai fait comme ça :
[...]
var regExpPourCent = '<span class="data">([0-9]+\.[0-9]+%)<\/span>';
var regExpPourCent2 = '<span class="data">([0-9]+%)<\/span>';
[...]
try {
var assetAnnualReturn = html.match(regExpAssetAnnualReturn)[1].match(regExpPourCent)[1];
}
catch (e) {
var assetAnnualReturn = html.match(regExpAssetAnnualReturn)[1].match(regExpPourCent2)[1];
}
[...]
j'ai toujours une donnée sur le " AssetAnnualReturn " normalement...
mais peut-être que je peux rajouter à la suite un troisième ?
catch (e) {
var assetAnnualReturn = ''
}
.
EDIT : je vais pas refaire un sujet pour ça…. mais est-ce que je peux tronquer les résultats directement depuis ce script ? j'ai besoins que de 2 décimales sur l'ensemble des données pour pouvoir les confronter dans une mise en forme conditionnel ensuite..