ウェブサイトhttp://niftyindices.com/resources/holiday-calendar
からcsv
ファイルをダウンロードするために、次のコードを実行しています。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();
await page.goto('http://niftyindices.com/resources/holiday-calendar');
await page._client.send('Page.setDownloadBehavior', {behavior: 'allow',
downloadPath: '/tmp'})
await page.click('#exportholidaycalender');
await page.waitFor(5000);
await browser.close();
})();
headless: false
で機能し、ファイルを/Users/user/Downloads
にダウンロードします。 headless: true
では機能しません。
Puppeteerバージョン1.1.1
を使用してmacOS Sierra(MacBook Pro)で実行しています。Chromiumバージョン66.0.3347.0
を.local-chromium/
ディレクトリに取り込み、npm init
およびnpm i --save puppeteer
を使用しましたそれを設定します。
何が間違っているのでしょうか?
あなたの時間と助けに前もって感謝します、
このページでは、コンマ区切りの文字列を作成してCSVをダウンロードし、データ型を次のように設定してブラウザに強制的にダウンロードさせます。
let uri = "data:text/csv;charset=utf-8," + encodeURIComponent(content);
window.open(uri, "Some CSV");
これはchrome=で新しいタブを開きます。
このイベントを利用して、コンテンツを物理的にファイルにダウンロードできます。これが最善の方法かどうかはわかりませんが、うまく機能します。
const browser = await puppeteer.launch({
headless: true
});
browser.on('targetcreated', async (target) => {
let s = target.url();
//the test opens an about:blank to start - ignore this
if (s == 'about:blank') {
return;
}
//unencode the characters after removing the content type
s = s.replace("data:text/csv;charset=utf-8,", "");
//clean up string by unencoding the %xx
...
fs.writeFile("/tmp/download.csv", s, function(err) {
if(err) {
console.log(err);
return;
}
console.log("The file was saved!");
});
});
const page = await browser.newPage();
.. open link ...
.. click on download link ..
問題は、ダウンロードが完了する前にブラウザが閉じることです。
応答からファイルサイズとファイルの名前を取得し、監視スクリプトを使用してダウンロードしたファイルからファイルサイズを確認し、ブラウザーを閉じます。
これは一例です:
const filename = <set this with some regex in response>;
const dir = <watch folder or file>;
// Download and wait for download
await Promise.all([
page.click('#DownloadFile'),
// Event on all responses
page.on('response', response => {
// If response has a file on it
if (response._headers['content-disposition'] === `attachment;filename=${filename}`) {
// Get the size
console.log('Size del header: ', response._headers['content-length']);
// Watch event on download folder or file
fs.watchFile(dir, function (curr, prev) {
// If current size eq to size from response then close
if (parseInt(curr.size) === parseInt(response._headers['content-length'])) {
browser.close();
this.close();
}
});
}
})
]);
応答での検索方法を改善することもできますが、これが役立つことを願っています。
昨日 このスレッド とStack Overflowを熟読し、認証セッションでヘッドレスモードでダウンロードリンクをクリックしてPuppeteerにcsvファイルをダウンロードさせる方法を見つけようとしました。私の場合、ここで受け入れられた回答はtargetcreated
をトリガーせず、次の回答は何らかの理由で認証されたセッションを保持しなかったため、私の場合はうまくいきませんでした。 この記事 日を保存しました。要するに、fetch
。うまくいけば、これが他の人の助けになります。
const res = await this.page.evaluate(() =>
{
return fetch('https://example.com/path/to/file.csv', {
method: 'GET',
credentials: 'include'
}).then(r => r.text());
});
ログインの背後からファイルをダウンロードする必要がありましたが、これはPuppeteerによって処理されていました。 targetcreated
はトリガーされていませんでした。最後に、PuppeteerインスタンスからCookieをコピーした後、request
でダウンロードしました。
この場合、ファイルをストリーミングしていますが、同じくらい簡単に保存できます。
res.writeHead(200, {
"Content-Type": 'application/octet-stream',
"Content-Disposition": `attachment; filename=secretfile.jpg`
});
let cookies = await page.cookies();
let jar = request.jar();
for (let cookie of cookies) {
jar.setCookie(`${cookie.name}=${cookie.value}`, "http://secretsite.com");
}
try {
var response = await request({ url: "http://secretsite.com/secretfile.jpg", jar }).pipe(res);
} catch(err) {
console.trace(err);
return res.send({ status: "error", message: err });
}
ここでの答えはどれも役に立たなかったので、この問題に対する別の解決策があります。
Webサイトにログインし、.csvレポートをダウンロードする必要がありました。私が何を試みたとしても、頭は大丈夫だった、頭なしは失敗した。ネットワークエラーを見ると、ダウンロードは中止されていますが、その理由を(すばやく)判断できませんでした。
そのため、リクエストをインターセプトし、node-fetchを使用してパペットの外部でリクエストを行いました。これには、フェッチオプション、ボディ、ヘッダーをコピーし、アクセスCookieを追加する必要がありました。
幸運を。