私は exposeFunction()
を使用してヘッドレスChrome内で何かを実行する非常に単純な Puppeteer スクリプトを持っています。
_(async function(){
var log = console.log.bind(console),
puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
var functionToInject = function(){
return window.navigator.appName;
}
await page.exposeFunction('functionToInject', functionToInject);
var data = await page.evaluate(async function(){
console.log('woo I run inside a browser')
return await functionToInject();
});
console.log(data);
await browser.close();
})()
_
これは失敗します:
_ReferenceError: window is not defined
_
注入された関数を指します。ヘッドレスChrome内でwindow
にアクセスするにはどうすればよいですか?
代わりにevaluate()
を実行できることはわかっていますが、これは動的に渡す関数では機能しません。
_(async function(){
var log = console.log.bind(console),
puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
var data = await page.evaluate(async function(){
console.log('woo I run inside a browser')
return window.navigator.appName;
});
console.log(data);
await browser.close();
})()
_
evaluate
関数evaluate
を使用して動的スクリプトを渡すことができます。
(async function(){
var puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
var functionToInject = function(){
return window.navigator.appName;
}
var data = await page.evaluate(functionToInject); // <-- Just pass the function
console.log(data); // outputs: Netscape
await browser.close();
})()
addScriptTag
およびreadFileSync
関数を別のファイルに保存し、addScriptTag
を使用して関数を使用できます。
await page.addScriptTag({path: 'my-script.js'});
またはevaluate
with readFileSync
。
await page.evaluate(fs.readFileSync(filePath, 'utf8'));
または、パラメータ化された関数を文字列としてpage.evaluate
に渡します。
await page.evaluate(new Function('foo', 'console.log(foo);'), {foo: 'bar'});
これに対処するために他の方法が必要ですか? runnable
関数:Dにしてみませんか?
function runnable(fn) {
return new Function("arguments", `return ${fn.toString()}(arguments)`);
}
上記は、指定された引数で新しい関数を作成します。必要な関数を渡すことができます。
window
を指定した次の関数と引数
function functionToInject() {
return window.location.href;
};
約束も完璧に機能し、
function functionToInject() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(window.location.href);
}, 5000);
});
}
引数付きで、
async function functionToInject(someargs) {
return someargs; // {bar: 'foo'}
};
evaluate
を使用して目的の関数を呼び出します。
var data = await page.evaluate(runnable(functionToInject), {bar: "foo"});
console.log(data); // shows the location
exposeFunction()
は、このジョブに適したツールではありません。
page.exposeFunction(name、puppeteerFunction)
puppeteerFunction Puppeteerのコンテキストと呼ばれるコールバック関数。
「人形遣いの文脈で」は少し曖昧ですが、evaluate()
のドキュメントをチェックしてください:
page.evaluateHandle(pageFunction、... args)
評価されるpageFunction関数ページコンテキスト
exposeFunction()
は、ページ内で実行される関数を公開しませんが、ノードで実行される関数を公開します呼び出されるページから。
evaluate()
を使用する必要があります:
あなたの問題はpage.exposeFunction()
があなたの関数にPromise
を返すという事実に関係しているかもしれません(async
とawait
の使用が必要です)。これは、関数が ブラウザー内で実行される ではなく、nodejs
アプリケーション内で行われ、その結果がブラウザーコードとの間でやり取りされるために発生します。これが、page.exposeFunction()
に渡された関数が実際の結果ではなくpromiseを返すようになった理由です。そして、関数がwindow
(ブラウザーではなく)内で実行され、nodejs
内にnodejs
がないため、window
関数が定義されていない理由を説明します利用可能な定義。
関連する質問: