2017-01-07 3 views
0

Je suis très nouveau sur NodeJs et NightmareJs. J'ai besoin de télécharger plusieurs fichiers de la même page en utilisant le plugin nightmare-inline-download. Jusqu'à présent, mon code ci-dessous peut télécharger le premier fichier. Mais je ne peux pas comprendre comment télécharger tous les fichiers liés à la page, c'est-à-dire, comment boucler click(selector).download() de la bonne façon. De plus, comment vais-je céder sur les téléchargements en boucle pour obtenir tous les noms de fichiers téléchargés?Comment puis-je télécharger plusieurs fichiers en série avec NighmareJs?

Notez les balises HTML <a> Je dois cliquer sur: <a target="_blank" class="download-link">Download</a>. Il n'y a pas d'attribut href; cliquer sur la balise déclenche un script qui lance le téléchargement.

Le site ne permet de lancer qu'un seul téléchargement à la fois.

Voici mon code à ce jour:

var Nightmare = require('nightmare'); 
require('nightmare-inline-download')(Nightmare); 
var nightmare = Nightmare({ show: false }); 
nightmare 
    .goto(pageUrl) 
    .evaluate({ 
    var links = document.querySelectorAll('.download-link'); 
    for(var i = 0, i < links.length; i++) { 
     links[i].setAttribute('download-this', 'true'); 
    } 
    }) 
    .click('[download-this="true"]') // will select just the first element 
    .download() 
    .end() 
    .then(() => { 
    console.log('done'); 
    }); 

Répondre

2

répondre à ma propre question. Après avoir lu this, this et this à plusieurs reprises, je me suis dit comment combiner sélecteurs et promet de boucle sur un clic(). Télécharger(). La clé est de donner à chaque lien de téléchargement de evaluer() son propre identifiant unique, puis de retourner un tableau des identifiants. Après cela .then peut réduire le tableau à une liste de promesses, où chaque promesse clique et télécharge l'élément sélectionné par ID unique. Un dernier .then débute les téléchargements. Le code devient:

var Nightmare = require('nightmare'); 
require('nightmare-inline-download')(Nightmare); 
var nightmare = Nightmare({ show: false }); 
nightmare 
    .goto(pageUrl) 
    .evaluate({ 
    var links = document.querySelectorAll('.download-link'); 
    var ids = []; 
    for(var i = 0, i < links.length; i++) { 
     links[i].setAttribute('download-this', i); 
     ids.push(i); 
    } 
    return ids 
    }) 
    .then(function (ids) { 
    return ids.reduce(function (accumulator, id) { 
     return accumulator.then(function (results) { 
     nightmare 
      .click('[download-this=["' + id + '"]') 
      .download(); 
     results.push(id); 
     return results; // ids of downloaded files 
     }) 
    }, Promise.resolve([])) 
    }) 
    .then(function (results) { 
    console.log('results', results); 
    return nightmare.end() 
    }) 
    .catch(function (error) { 
    console.error('Error:', error); 
    return nightmare.end() 
    }); 

Maintenant, si je dois imprimer des informations sur chaque téléchargement, au lieu de retourner les ids de fichier téléchargé, ajouter un .then après download() retourner les informations sur le téléchargement terminé. Ce morceau de code que j'ai pris de ce test script, qui rétrospectivement est semblable au script que je présente dans cette réponse! Ainsi, le code correspondant change de cette façon, de

nightmare 
     .click('[download-this=["' + id + '"]') 
     .download(); 
    results.push(id); 
    return results; // ids of downloaded files 

à

return nightmare 
     .click('[download-this=["' + id + '"]') 
     .download() 
     .then(info => { 
     results.push(info); 
     return results; // info about downloaded files 
     });