web-dev-qa-db-fra.com

Comment analyser une chaîne HTML dans le script Google Apps sans utiliser XmlService?

Je souhaite créer un grattoir à l'aide de Google Spreadsheets avec Google Apps Script. Je sais que c'est possible et j'ai vu des tutoriels et des discussions à ce sujet.

L'idée principale est d'utiliser:

  var html = UrlFetchApp.fetch('http://en.wikipedia.org/wiki/Document_Object_Model').getContentText();
  var doc = XmlService.parse(html);

Et puis obtenir et travailler avec les éléments. Cependant, la méthode

XmlService.parse()

Ne fonctionne pas pour certaines pages. Par exemple, si j'essaye:

function test(){
    var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
    var parse = XmlService.parse(html);
}

Je reçois l'erreur suivante:

Error on line 225: The entity name must immediately follow the '&' in the entity reference. (line 3, file "")

J'ai essayé d'utiliser string.replace() pour éliminer les caractères qui sont apparemment à l'origine de l'erreur, mais cela ne fonctionne pas. Toutes sortes d'autres erreurs apparaissent. Le code suivant par exemple:

function test(){
    var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
    var regExp = new RegExp("&", "gi");
    html = html.replace(regExp,"");

    var parse = XmlService.parse(html);
}

Me donne l'erreur suivante:

Error on line 358: The content of elements must consist of well-formed character data or markup. (line 6, file "")

Je crois que c'est un problème avec la méthode XmlService.parse().

J'ai lu dans cette discussion:

Table d'analyse de Google App Script à partir de HTML désordonné et Quel est le meilleur moyen d'analyser le langage HTML dans le script Google Apps que l'on peut utiliser une méthode obsolète appelée xml.parse() qui accepte un deuxième paramètre permettant l'analyse HTML. Cependant, comme je l’ai mentionné, il est obsolète et je ne trouve aucune documentation à ce sujet où que ce soit. La xml.parse() semble analyser la chaîne, mais j'ai du mal à travailler avec les éléments en raison du manque de documentation. Et ce n’est pas non plus la solution la plus sûre à long terme, car elle peut être désactivée à tout moment.

Je souhaite donc savoir comment analyser ce code HTML dans le script Google Apps.

J'ai aussi essayé:

function test(){

    var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
    var htmlOutput = HtmlService.createHtmlOutput(html).getContent();

    var parse = XmlService.parse(htmlOutput);
}

Mais cela ne fonctionne pas, je reçois cette erreur:

Contenu HTML mal formé:

J'ai envisagé d'utiliser une bibliothèque open source pour analyser le code HTML, mais je n'en ai trouvé aucun.

Mon objectif ultime est d'obtenir des informations à partir d'un ensemble de pages telles que Prix, Lien, Nom du produit, etc. J'ai réussi à le faire en utilisant une série de RegEx:

var ss = SpreadsheetApp.getActiveSpreadsheet();
  var linksSheet = ss.getSheetByName("Links");
  var resultadosSheet = ss.getSheetByName("Resultados");

function scrapyLoco(){

  var links = linksSheet.getRange(1, 1, linksSheet.getLastRow(), 1).getValues();
  var arrayGrandao = [];
  for (var row =  0, len = links.length; row < len; row++){
   var link = links[row];


   var arrayDeResultados = pegarAsCoisas(link[0]);
   Logger.log(arrayDeResultados);
   arrayGrandao.Push(arrayDeResultados);
  }   


  resultadosSheet.getRange(2, 1, arrayGrandao.length, arrayGrandao[0].length).setValues(arrayGrandao);

}


function pegarAsCoisas(linkDoProduto) {
  var resultadoArray = [];

  var html = UrlFetchApp.fetch(linkDoProduto).getContentText();
  var regExp = new RegExp("<h1([^]*)h1>", "gi");
  var h1Html = regExp.exec(html);
  var h1Parse = XmlService.parse(h1Html[0]);
  var h1Output = h1Parse.getRootElement().getText();
  h1Output = h1Output.replace(/(\r\n|\n|\r|(^( )*))/gm,"");

  regExp = new RegExp("Ref.: ([^(])*", "gi");
  var codeHtml = regExp.exec(html);
  var codeOutput = codeHtml[0].replace("Ref.: ","").replace(" ","");

  regExp = new RegExp("margin-top: 5px; margin-bottom: 5px; padding: 5px; background-color: #699D15; color: #fff; text-align: center;([^]*)/div>", "gi");
  var descriptionHtml = regExp.exec(html);
  var regExp = new RegExp("<p([^]*)p>", "gi");
  var descriptionHtml = regExp.exec(descriptionHtml);
  var regExp = new RegExp("^[^.]*", "gi");
  var descriptionHtml = regExp.exec(descriptionHtml);
  var descriptionOutput = descriptionHtml[0].replace("<p>","");
  descriptionOutput = descriptionOutput+".";

  regExp = new RegExp("ecom(.+?)Main.png", "gi");
  var imageHtml = regExp.exec(html);
  var comecoDaURL = "https://www.nespresso.com/";
  var imageOutput = comecoDaURL+imageHtml[0];

  var regExp = new RegExp("nes_l-float nes_big-price nes_big-price-with-out([^]*)p>", "gi");
  var precoHtml = regExp.exec(html);
  var regExp = new RegExp("[0-9]*,", "gi");
  precoHtml = regExp.exec(precoHtml);
  var precoOutput = "BRL "+precoHtml[0].replace(",","");

  resultadoArray = [codeOutput,h1Output,descriptionOutput,"Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines",
                    "Máquina",linkDoProduto,imageOutput,"new","in stock",precoOutput,"","","","Nespresso",codeOutput];

  return resultadoArray;
}

Mais cela demande beaucoup de temps à programmer, il est très difficile de le changer dynamiquement et n’est pas très fiable.

Il me faut un moyen d’analyser ce code HTML et d’accéder facilement à ses éléments . Ce n’est pas un ajout. mais un simple script google app ..

12
user3347814

Je l'ai fait dans Vanilla js. Pas de vrais analyses HTML. Essayez juste d’obtenir du contenu d’une chaîne (url):

function getLKKBTC() {
  var url = 'https://www.lykke.com/exchange';
  var html = UrlFetchApp.fetch(url).getContentText();
  var searchstring = '<td class="ask_BTCLKK">';
  var index = html.search(searchstring);
  if (index >= 0) {
    var pos = index + searchstring.length
    var rate = html.substring(pos, pos + 6);
    rate = parseFloat(rate)
    rate = 1/rate
    return parseFloat(rate);
  }
  throw "Failed to fetch/parse data from " + url;
}
8
Fabian Thommen

Cela a été discuté avant. Voir ici: Quel est le meilleur moyen d’analyser le code HTML dans le script Google Apps

Contrairement au service XML, le XMLService ne pardonne pas beaucoup le code HTML malformé. Le truc dans la réponse de Justin Bicknell fait le travail. Même si le service XML est obsolète, il continue de fonctionner. 

5
Sujay Phadke

J'ai fait des cheeriogs pour ton problème. cela fonctionne sur GAS comme cheerio, qui est une api de type jQuery. Vous pouvez faire ça comme ça.

const content = UrlFetchApp.fetch('https://example.co/').getContentText();
const $ = Cheerio.load(content);
Logger.log($('p .blah').fist().text()); // blah blah blah ...

Voir aussi https://github.com/asciian/cheeriogs

4
asciian

Sachez que certains sites Web peuvent ne pas autoriser le nettoyage automatisé de leur contenu. Veuillez donc consulter leurs conditions d'utilisation ou leur service avant d'utiliser Apps Script pour extraire le contenu.

La XmlService ne fonctionne qu'avec les documents XML valides, et la plupart du HTML (en particulier HTML5) n'est pas valide. Une version précédente de XmlService, simplement appelée Xml, autorisait une analyse "indulgente", ce qui lui permettrait également d’analyser le code HTML. Ce service a été interrompu en 2013, mais pour le moment, il fonctionne toujours. Les documents de référence ne sont plus disponibles, mais ce ancien tutoriel montre son utilisation.

Une autre solution consiste à utiliser un service tel que Kimono , qui gère le grattage et l’analyse de pièces et fournit une API simple que vous pouvez appeler via UrlFetchApp pour récupérer les données structurées.

2
Eric Koleda

Pourriez-vous utiliser javascript pour analyser le code HTML? Si votre script Google Apps a récupéré le code HTML sous forme de chaîne, puis l'a renvoyé à une fonction javascript, il semble que vous puissiez l'analyser correctement en dehors du script Google Apps. Toutes les balises que vous souhaitez gratter peuvent être envoyées à une fonction Google Apps dédiée qui enregistre le contenu.

Vous pourriez probablement accomplir ceci plus facilement avec jQuery .

1
Eric Dauenhauer

J'ai trouvé une alternative très intéressante à utiliser Google App Script. Il s’appelle PhantomJS Cloud . On peut utiliser urlFetchApp pour accéder à l’API. Cela permet d'exécuter du code Jquery sur les pages, ce qui simplifie énormément la vie.

0
user3347814

peut-être pas l’approche la plus propre, mais un simple traitement de chaîne fait aussi l'affaire sans xmlservice:

var url = 'https://somewebsite.com/?q=00:11:22:33:44:55';
var html = UrlFetchApp.fetch(url).getContentText();
// we want only the link text displayed from here:
//<td><a href="/company/ubiquiti-networks-inc">Ubiquiti Networks Inc.</a></td>
var string1 = html.split('<td><a href="/company/')[1]; // all after '<td><a href="/company/'
var string2 = string1.split('</a></td>')[0];           // all before '</a></td>'
var string3 = string2.split('>')[1];                   // all after '>'
Logger.log('link text: '+string3);                     // string3 => "Ubiquiti Networks Inc."
0
vchrizz