2014-11-24 82 views
8

我使用夢魘爲當今的報紙創建自動化下載程序。我設法登錄並進入指定頁面。但是我無法找到如何使用夢魘下載文件。使用夢魘下載文件

var Nightmare = require('nightmare'); 
new Nightmare() 
    .goto('https://login.nrc.nl/login?service=http://digitaleeditie.nrc.nl/welkom') 
    .type('input[name="username"]', 'Username') 
    .type('input[name="password"]','Password') 
    .click('button[type="submit"]') 
    .wait() 
    .goto('http://digitaleeditie.nrc.nl/digitaleeditie/NH/2014/10/20141124___/downloads.html') 
    .wait() 
    .click('a[href="/digitaleeditie/helekrant/epub/nrc_20141124.epub"]') 
    .wait() 

    .url(function(url) { 
     console.log(url) 
    }) 
    .run(function (err, nightmare) { 
     if (err) return console.log(err); 
     console.log('Done!'); 
    }); 

我試圖通過單擊下載按鈕來下載文件。但是,這似乎不起作用。

回答

4

當您點擊應該下載的內容時,PhantomJS(以及CasperJS和Nightmare)不會觸發下載(對話框)。所以,有必要自己下載它。如果您可以找到該文件的URL,那麼可以使用頁面上下文中的XMLHttpRequest輕鬆下載。

所以你需要兌換

.click('a[href="/digitaleeditie/helekrant/epub/nrc_20141124.epub"]') 

.evaluate(function ev(){ 
    var el = document.querySelector("[href*='nrc_20141124.epub']"); 
    var xhr = new XMLHttpRequest(); 
    xhr.open("GET", el.href, false); 
    xhr.overrideMimeType("text/plain; charset=x-user-defined"); 
    xhr.send(); 
    return xhr.responseText; 
}, function cb(data){ 
    var fs = require("fs"); 
    fs.writeFileSync("book.epub", data, "binary"); 
}) 

您還可以使用請求二進制數據的新方式。

.evaluate(function ev(){ 
    var el = document.querySelector("[href*='.pdf']"); 
    var xhr = new XMLHttpRequest(); 
    xhr.open("GET", el.href, false); 
    xhr.responseType = "arraybuffer"; 
    xhr.send(); 

    var bytes = []; 
    var array = new Uint8Array(xhr.response); 
    for (var i = 0; i < array.length; i++) { 
     bytes[i] = array[i]; 
    } 
    return bytes; 
}, function cb(data){ 
    var fs = require("fs"); 
    fs.writeFileSync("book.epub", new Buffer(data), "binary"); 
}) 

這兩種方式都被描述爲on MDNHere是一個示例腳本,顯示了概念驗證。

+0

我試圖實現這一點。但是,這隻能下載一個具有相同名稱的4k文件。它不下載整個文件。 – 2014-11-25 13:18:40

+0

4k有點任意。內容是什麼?也許這是一個錯誤頁面。 – 2014-11-25 13:24:30

+0

這是一個大小爲4k的epub文件。如果在文本編輯器中打開,它只包含null。 – 2014-11-25 13:30:33

1

我使用request module獲得了我的下載超級簡單,如here所述。爲了

var Nightmare = require('nightmare'); 
var fs = require('fs'); 
var request = require('request'); 

new Nightmare() 
    .goto('https://login.nrc.nl/login?service=http://digitaleeditie.nrc.nl/welkom') 
    .insert('input[name="username"]', 'Username') 
    .insert('input[name="password"]','Password') 
    .click('button[type="submit"]') 
    .wait() 
    .goto('http://digitaleeditie.nrc.nl/digitaleeditie/NH/2014/10/20141124___/downloads.html') 
    .wait() 
    .then(function() { 
    download('http://digitaleeditie.nrc.nl/digitaleeditie/helekrant/epub/nrc_20141124.epub', 'myBook.epub', function() { 
     console.log('done'); 
    }); 
    }) 
    .catch(function (err) { 
    console.log(err); 
    }) 

function download(uri, filename, callback) { 
    request.head(uri, function() { 
    request(uri).pipe(fs.createWriteStream(filename)).on('close', callback); 
    }); 
} 

運行npm i request使用request

+0

代碼錯誤 - 調用download()時參數之間缺少',' – 2018-01-22 19:51:57

2

有一個Nightmare download plugin。 您可以只需用下面這段代碼下載文件:

var Nightmare = require('nightmare'); 
 
require('nightmare-download-manager')(Nightmare); 
 
var nightmare = Nightmare(); 
 
nightmare.on('download', function(state, downloadItem){ 
 
    if(state == 'started'){ 
 
    nightmare.emit('download', '/some/path/file.zip', downloadItem); 
 
    } 
 
}); 
 

 
nightmare 
 
    .downloadManager() 
 
    .goto('https://github.com/segmentio/nightmare') 
 
    .click('a[href="/segmentio/nightmare/archive/master.zip"]') 
 
    .waitDownloadsComplete() 
 
    .then(() => { 
 
    console.log('done'); 
 
    });

0

夢魘將正常下載,如果你點擊下載鏈接。

const Nightmare   = require('nightmare'); 
const show    = (process.argv[2].includes("true")) ? true : false; 
const nightmare   = Nightmare({ show: show }); 

nightmare 
    .goto("https://github.com/segmentio/nightmare") 
    .click('a[href="/segmentio/nightmare/archive/master.zip"]') 
    .end(() => "Done!") 
    .then((value) => console.log(value));