添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
逃课的橙子  ·  CBETA 漢文大藏經·  2 周前    · 
逃跑的面包  ·  How to get effective ...·  2 月前    · 
私奔的山楂  ·  Bar Graphs in Stata·  2 月前    · 
坚强的南瓜  ·  .load() : ...·  4 月前    · 

Puppeteer ってソラで書けますか? ぼくは書けないので pptr.dev にアクセスしてコピペしてます。

Puppeetteer でファイルをダウンロードする方法はわかりやすい API としては提供されておらず、Stackoverflow を毎回見てる。これも古い方法が出回ったままだったりするので令和4年現在での最新版と思われる方法を書いておく。

例として、 https://motemen.github.io/beautiful-graph-maker/ から画像をダウンロードしてみる。これは JavaScript で画像を生成してるのでブラウザのインスタンスが必要なやつだ。

Chrome DevTools Protocol 経由でダウンロードする

Chrome DevTools Protocol ってのは Chrome その他のブラウザをプログラムから操作・計測・デバッグ等々するためのプロトコルらしい。Pptr からこれにアクセスする API があるので、こちらを経由する。

const cdpSession = await page.target().createCDPSession();

CDP 経由で Browser.setDownloadBehavior を呼ぶ。世間的には Page.setDownloadBehavior を呼ぶ、というサンプルが多いようだけど、これは deprecated らしいので今はこちら。

await cdpSession.send("Browser.setDownloadBehavior", {
  behavior: "allow",
  downloadPath,
  eventsEnabled: true,

ダウンロード完了を知りたいので eventsEnabled を true にしておく。behavior については後述。

イベントが有効になったので Browser.downloadProgress イベントをリスンする。これでダウンロード完了のタイミングがわかる。

const downloaded = new Promise<void>((resolve, reject) => {
  cdpSession.on(
    "Browser.downloadProgress",
    (params: { state: "inProgress" | "completed" | "canceled" }) => {
      if (params.state == "completed") {
        resolve();
      } else if (params.state == "canceled") {
        reject("download cancelled");

あとは Promise の使い方という感じで、適当にタイムアウトを設定しつつダウンロードする。ちなみにダウンロードされた正確なファイル名は分からないので、ダウンロード先のディレクトリは毎回新しいものを作るようにするのがよさそう。

Browser.setDownloadBehavior に behavior: "allowAndName" を指定するとファイル名が Browser.downloadProgress で取得される guid になるようだけど、この場合拡張子が消えるのに注意。Browser.downloadWillBegin イベントで suggestedFilename を取得しておくといいだろう。

await button.click(); // これでダウンロード開始
await Promise.race([
  downloaded,
  new Promise<boolean>((_resolve, reject) => {
    setTimeout(() => {
      reject("download timed out");
    }, DOWNLOAD_TIMEOUT);

Playwright だと

ちなみに Puppeteer と同様にブラウザをプログラムから扱う microsoft/playwright というライブラリはつづりが分かりやすいだけでなく、ダウンロード用の API も提供してるらしい。これだけでいけた。

const [download] = await Promise.all([
  page.waitForEvent("download"),
  button.click(),
//   path: '/var/folders/hm/0xt2zy.../279506cd-00e1-43d5-ad4f-f72909ba706c',
//   suggestedFilename: 'graph.png'
console.log({
  path: await download.path(),
  suggestedFilename: download.suggestedFilename(),

path は guid 的なものになるようなので、suggestedFilename から拡張子を取得する。

今回使ったコードの全体は Gist にある: https://gist.github.com/motemen/ce4ca5d4134b31a11725f3461a09c136