Puppeteer,保存网页和图片

10

我想使用Nodejs和puppeteer将网页保存下来以便离线使用。我看到很多例子都是这样做的:

await page.screenshot({path: 'example.png'});

但对于较大的网页来说,这并不是一个选项。因此,在puppeteer中更好的选择是加载页面,然后保存为:

const html = await page.content();
// ... write to file

好的,没问题。现在我要像Twitter一样滚动页面。因此,我决定在Puppeteer页面中阻止所有图像:

page.on('request', request => {
    if (request.resourceType() === 'image') {
        const imgUrl = request.url()
        download(imgUrl, 'download').then((output) => {
            images.push({url: output.url, filename: output.filename})
        }).catch((err) => {
            console.log(err)
        })
        request.abort()
    } else {
        request.continue()
    }
})

好的,我现在使用了“npm download”库来下载所有图片。是的,下载的图片都很好:D。

现在当我保存内容时,我想将其指向源中的离线图片。

const html = await page.content();

但现在我想要替换所有的

标签为 标签。
<img src="/pic.png?id=123"> 
<img src="https://twitter.com/pics/1.png">

并且还有像这样的事情:
<div style="background-image: url('this_also.gif')></div>

在Puppeteer中有没有一种方法可以爬取一个大页面并将整个内容离线存储?同时包括Javascript和CSS。

更新

目前我将再次使用Puppeteer打开大的HTML文件。

然后拦截所有文件,如: https://dom.com/img/img.jpg,/file.jpg,....

request.respond({
    status: 200,
    contentType: 'image/jpeg',
    body: '..'
});

我也可以使用Chrome扩展程序来完成这项任务。但是,我希望能够在选项页面中添加一些功能,类似于page.pdf()的功能。


我认为网页太动态了,不适合做这样的事情...(取决于你想花多少时间在上面)。你的最终目标是什么,只是查看吗? - Cody G
问题是如何操作HTML?如果是这样,您可以使用来自Node的Cheerio或来自page.evaluate的jQuery。 - pguardiario
1
问题是如何指向本地下载。当您有CSS、JavaScript和图像时。 - Johan Hoeksma
@Cody,目标是保存大型网站(如Twitter、Facebook等)以供离线使用。 - Johan Hoeksma
2个回答

10

让我们回到开始,您可以使用fullPage来截取屏幕截图。

await page.screenshot({path: 'example.png', fullPage: true});

如果你真的想要离线下载所有资源,是可以做到的:

const fse = require('fs-extra');

page.on('response', (res) => {
    // save all the data to SOMEWHERE_TO_STORE
    await fse.outputFile(SOMEWHERE_TO_STORE, await res.buffer());
});

然后,使用puppeteer离线浏览网站时,一切都正常。

await page.setRequestInterception(true);
page.on('request', (req) => {
    // handle the request by responding data that you stored in SOMEWHERE_TO_STORE
    // and of course, don't forget THE_FILE_TYPE
    req.respond({
        status: 200,
        contentType: THE_FILE_TYPE,
        body: await fse.readFile(SOMEWHERE_TO_STORE),
    });
});


4
最好依赖于 requestfinished 事件。 - Denis Glotov

-1

目前我将使用:

https://github.com/dosyago/22120

这个项目的目标:

This project literally makes your web browsing available COMPLETELY OFFLINE. 
Your browser does not even know the difference. It's literally that amazing. Yes.

很棒,但是任何MITM代理都可以做到同样的事情。 - pouya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接