gpt4 book ai didi

javascript - Puppeteer 从外部 .js 文件调用 javascript 函数

转载 作者:行者123 更新时间:2023-12-04 17:18:44 28 4
gpt4 key购买 nike

任何人都知道如何 调用 javascript 函数 来自 puppeteer 师这不是内联的,而是在 中外部.js 文件。如果它在 html->head->script 标记中内联,则它可以工作,但如果脚本标记指向外部 .js 文件,则不能
示例 HTML 文件

<html>
<head>
<script type="text/javascript">
function inlineFunction() {
window.location.replace('https://www.geeksforgeeks.org');
}
</script>
<script src="script.js" type="text/javascript">
</script>
</head>
<body>
<p>Hello</p>
<p>this is an online html</p>
<p>Link with tag a <a href="https://www.geeksforgeeks.org" name="arivalink">Href Link</a></p>
<p>Link with inline java script - <a href="#" onClick='inlineFunction();'>Inline JS link</a></p><!-- Works -->
<p>Link with external JS file w/o tagname - <a href="#" onClick='fileFunction();'>Ext JS Link</a></p><!-- Does not work -->
<p>Link with external JS file w/ tagname - <a href="#" onClick='fileFunction();' name="geeksLink">Ext JS Link</a></p><!-- Does not work -->
</body>
</html>
示例 Javascript 文件
/*----------------------------------------------------*/
/* External Javascript File */
/*----------------------------------------------------*/

function fileFunction() {

window.location.replace('https://www.geeksforgeeks.org');

}
Puppeteer 代码示例
const puppeteer = require('puppeteer');

async function start() {
const browser = await puppeteer.launch({
headless: false
});

const page = await browser.newPage();

//Change the path of "url" to your local path for the html file
const url = 'file:///Users/sam.gajjar/SG/Projects/headless-chrome/sample.html';
var link = '[name="link"]';

console.log("Main URL Called");
await page.goto(url);

console.log("Link via HTML tag A called");
await page.click(link);

await page.waitForTimeout(5000) // Wait 5 seconds
.then(() => page.goBack());

console.log("Callng inline JS Function");
await page.evaluate(() => inlineFunction());

await page.waitForTimeout(5000) // Wait 5 seconds
.then(() => page.goBack());

console.log("Callng extjs file Function");
await page.evaluate(() => fileFunction());

await page.waitForTimeout(5000) // Wait 5 seconds
.then(() => page.goBack());

// console.log("Callng extjs file Function w/tag name");
// const element = await page.$$('[a href="#"]');

// await page.waitForTimeout(5000)
// .then(() => page.goBack());
}

start();

最佳答案

首先,[name="link"]应该是 [name="arivalink"]匹配你的 DOM。我认为这是一个错字。
另外,我建议使用 Promise.all navigation pattern而不是 waitForTimeout这可能会导致竞争条件(尽管在这种情况下这似乎与问题无关)。
至于主要问题,外部文件工作得很好,所以这是一个红鲱鱼。您可以通过调用 page.evaluate(() => fileFunction()) 来证明这一点在导航到 sample.html 之后.
真正的问题是,当您使用 window.location.replace('https://www.geeksforgeeks.org'); 导航时, Chromium 不会将该操作推送到历史堆栈中。它正在替换当前的 URL,所以 page.goBack()回到原来的about:blank而不是 sample.html如你所料。 about:blank没有 fileFunction在里面,所以 Puppeteer 扔了。
现在,当您单击 [name="link"]使用 Puppeteer,确实会推送历史堆栈,所以 goBack工作得很好。
您可以通过加载 sample.html 来重现此行为在浏览器中并在没有 Puppeteer 的情况下手动导航。
长话短说,如果您在浏览器上下文中使用 evaluate 调用函数运行 window.location.replace , 你不能依赖 page.goBack .您需要使用 page.goto返回 sample.html .
有一个有趣的细微差别:如果你使用 page.click调用运行 location.replace("...") 的 JS , Puppeteer 将推送历史堆栈和page.goBack将按预期运行。如果您使用 page.evaluate(() => location.replace("...")); 调用相同的 JS 逻辑, Puppeteer 不会将当前 URL 推送到历史堆栈和 page.goBack不会像你期望的那样工作。 evaluate行为更符合“手动”浏览(即作为一个在 GUI 上使用鼠标和键盘的人)。
这是演示所有这些的代码。一切都在同一个目录和node index.js运行 Puppeteer(我使用 Puppeteer 9.0.0)。
脚本.js

const replaceLocation = () => location.replace("https://www.example.com");
const setLocation = () => location = "https://www.example.com";
示例.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>sample</title>
</head>
<body>
<div>
<a href="https://www.example.com">normal link</a> |
<a href="#" onclick="replaceLocation()">location.replace()</a> |
<a href="#" onclick="setLocation()">location = ...</a>
</div>
<script src="script.js"></script>
</body>
</html>
index.js
const puppeteer = require("puppeteer");

const url = "file:///Users/sam.gajjar/SG/Projects/headless-chrome/sample.html";
const log = (() => {
let logId = 0;
return (...args) => console.log(logId++, ...args);
})();
let browser;

(async () => {
browser = await puppeteer.launch({
headless: false,
slowMo: 500,
});
const [page] = await browser.pages();
await page.goto(url);

// display the starting location
log(page.url()); // 0 sample.html

// click the normal link and pop the browser stack with goBack
await Promise.all([
page.waitForNavigation(),
page.click("a:nth-child(1)"),
]);
log(page.url()); // 1 example.com
await page.goBack();
log(page.url()); // 2 sample.html

// fire location.replace with click
await Promise.all([
page.waitForNavigation(),
page.click("a:nth-child(2)"), // pushes history (!)
]);
log(page.url()); // 3 example.com
await page.goBack();
log(page.url()); // 4 sample.html

// fire location.replace with evaluate
await Promise.all([
page.waitForNavigation(),
page.evaluate(() => replaceLocation()), // doesn't push history
]);
log(page.url()); // 5 example.com
await page.goBack();
log(page.url()); // 6 about:blank <--- here's your bug!

await page.goto(url); // go to sample.html from about:blank <-- here's the fix
log(page.url()); // 7 sample.html

// use location = and see that goBack takes us to sample.html
await Promise.all([
page.waitForNavigation(),
page.evaluate(() => setLocation()), // same behavior as page.click
]);
log(page.url()); // 8 example.com
await page.goBack();
log(page.url()); // 9 sample.html
})()
.catch(err => console.error(err))
.finally(async () => await browser.close())
;

关于javascript - Puppeteer 从外部 .js 文件调用 javascript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67539195/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com