是否可以使用 Puppeteer(无需网络服务器)通过无头 Chrome 打开本地 HTML 文件?我只能让它在本地服务器上工作。
我在
Puppeteer API文档中找到了
setContent()
和goto()
,但是:
page.goto
:无法使用本地文件或 file://
。page.setContent
:用于 HTML 字符串我刚刚在本地做了一个测试(你可以看到我在 Windows 上做了这个),puppeteer 愉快地使用 page.goto 和完整文件 url 打开我的本地 html 文件,并将其保存为 pdf:
'use strict';
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('file://C:/Users/compoundeye/test.html');
await page.pdf({
path: 'test.pdf',
format: 'A4',
margin: {
top: "20px",
left: "20px",
right: "20px",
bottom: "20px"
}
});
await browser.close();
})();
如果您需要使用相对路径可能想看看这个关于使用相对文件路径的问题:File Uri Scheme andrelative Files
如果文件在本地,使用 setContent 会比 goto 更好
var contentHtml = fs.readFileSync('C:/Users/compoundeye/test.html', 'utf8');
await page.setContent(contentHtml);
您可以在此处检查setContent和goto
之间的性能我们以本地 HTML 文件中的一个元素的屏幕截图为例。
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// __dirname is a global node variable that corresponds to the absolute
// path of the folder containing the currently executing file
await page.goto(`file://${__dirname}/pages/test.html`);
const element = await page.$('.myElement');
if (element) {
await element.screenshot({
path: `./out/screenshot.png`,
omitBackground: true,
});
}
await browser.close();
})();
仅当您还传递
file://
的引用时,导航到本地文件才有效,否则安全限制会阻止此操作成功。
为什么不打开HTML文件读取内容,然后“setContent”
我打开要加载到浏览器中的文件并复制 URL 以确保所有 \ 都正确。
await page.goto(`file:///C:/pup_scrapper/testpage/TM.html`);
您可以使用
file-url
准备要传递给 page.goto
的 URL:
const fileUrl = require('file-url');
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(fileUrl('file.html'));
await browser.close();
page.setContent()
有一些警告正如其他答案所述,您可以使用 Node API 读取文件,然后调用
page.setContent()
以获得比 page.goto()
更大的灵活性。但是,显示 about:blank(默认)页面时存在一些限制,例如未加载相关资源(更多信息此处)。
解决方法是创建一个空的
empty.html
文件,导航到该文件,然后调用 page.setContent()
:
// would typically load from a file
const html = '<!DOCTYPE html><title>Hello</title><p>World</p>';
await page.goto('file://empty.html', { waitUntil: 'load' });
await page.setContent(html, { waitUntil: 'networkidle0' });
如果您想在本地加载
file://
无法使用的其他资源,您可以利用page.setRequestInterception()
:
import path from 'path';
let resources = [
'style.css': {
content: Buffer.from('p {color: navy;}'),
mimetype: 'text/css'
}
]
page.on('request', interceptedRequest => {
const url = new URL(interceptedRequest.url());
if (url.protocol === 'file:' && url.pathname !== 'empty.html') {
const resourceName = path.basename(url.pathname); // Extract the file name
const resource = resources[resourceName];
if (resource) {
interceptedRequest.respond({
status: 200,
contentType: resource.mimetype,
body: resource.content,
});
} else {
interceptedRequest.abort();
}
} else {
interceptedRequest.continue();
}
});