web-dev-qa-db-ja.com

ヘッドレスを使用してパペットでファイルをダウンロードする方法:true?

ウェブサイト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 ..
6
Sumit Mishra

問題は、ダウンロードが完了する前にブラウザが閉じることです。

応答からファイルサイズとファイルの名前を取得し、監視スクリプトを使用してダウンロードしたファイルからファイルサイズを確認し、ブラウザーを閉じます。

これは一例です:

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());
});
2
MyCompassSpins

ログインの背後からファイルをダウンロードする必要がありましたが、これは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 });
    }
0

ここでの答えはどれも役に立たなかったので、この問題に対する別の解決策があります。

Webサイトにログインし、.csvレポートをダウンロードする必要がありました。私が何を試みたとしても、頭は大丈夫だった、頭なしは失敗した。ネットワークエラーを見ると、ダウンロードは中止されていますが、その理由を(すばやく)判断できませんでした。

そのため、リクエストをインターセプトし、node-fetchを使用してパペットの外部でリクエストを行いました。これには、フェッチオプション、ボディ、ヘッダーをコピーし、アクセスCookieを追加する必要がありました。

幸運を。

0