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")
image

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é.

je te donne une fonction personnalisée demain, elle devrait pouvoir fonctionner, il faut que j'affine

image
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.

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 image

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

( pour ces exemples en particuliers, pour lesquels je peux avoir un texte variable )

=IMPORTXML(A2,"//*[@class='assetHasTenants']/span")
=IMPORTXML(A2,"//*[@class='assetSection8']/span")

merci

je vais jeter un oeil ...

il faudra aussi tout récupérer en même temps (les 3 ou 4 données)

je vais jeter un oeil ...

même pour une seul recherche le script est assez long

( +/- 5min pour la recherche de AssetAnnualReturn par exemple)

d'où ma crainte avec plusieurs recherches

image

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...

image
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

image

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..

image

je n'ai pas obtenu un bon resultat avec ça

zut, désolé ...

pour le %, essaie ceci alors

var regExpPourCent = '<span class="data">([0-9]+[\.]{0,1}[0-9]+%)<\/span>';

pour le %, essaie ceci alors

On est bon comme ça ! Merci :)

Rechercher des sujets similaires à "grande quantite appels importxml solution alternative"