Puppeter从外部.js文件调用javascript函数
任何人都知道如何从puppeter调用javascript函数,该函数不是内联的,而是在external.js文件中。如果它在html->head->script标记中内联,则可以工作,但如果script标记指向外部.js文件,则不能工作 示例HTML文件Puppeter从外部.js文件调用javascript函数,javascript,puppeteer,Javascript,Puppeteer,任何人都知道如何从puppeter调用javascript函数,该函数不是内联的,而是在external.js文件中。如果它在html->head->script标记中内联,则可以工作,但如果script标记指向外部.js文件,则不能工作 示例HTML文件 <html> <head> <script type="text/javascript"> function inlineFunction
<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>
木偶演员代码示例
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。我想那是个打字错误
另一方面,我建议使用,而不是waitForTimeout
,这可能会导致竞争条件(尽管这似乎与本例中的问题无关)
至于主要问题,外部文件工作得很好,所以这是一个转移注意力的问题。您可以在导航到sample.html
之后立即调用page.evaluate(()=>fileFunction())
来证明这一点
真正的问题是当您使用window.location.replace('https://www.geeksforgeeks.org');代码>,Chromium没有将该操作推送到历史堆栈上。它将替换当前URL,因此page.goBack()
将返回原始about:blank
,而不是您所期望的sample.html
about:blank
中没有fileFunction
,所以木偶师抛出
现在,当您使用Puppeter单击[name=“link”]
时,确实会推送历史堆栈,因此goBack
工作正常
您可以通过在浏览器中加载sample.html
并在没有傀儡机的情况下手动导航来重现此行为
长话短说,如果您在浏览器上下文中使用运行window.location.replace的evaluate
调用函数,则不能依赖page.goBack
。您需要使用page.goto
返回sample.html
有一个有趣的细微差别:如果您使用页面。单击
调用运行位置的JS。替换(“…”
),Puppeter将推送历史堆栈和页面。goBack
将按预期运行。如果使用page.evaluate(()=>location.replace(“…”)调用相同的JS逻辑
,Puppeter将不会将当前URL推送到历史堆栈和页面。goBack
将无法按预期工作。evaluate
行为更符合“手动”浏览(即在GUI上使用鼠标和键盘的人)
下面是演示所有这些的代码。所有内容都放在同一个目录中,node index.js
运行puppeter(我使用了puppeter 9.0.0)
script.js
sample.html
样品
|
|
index.js
const puppeter=require(“木偶演员”);
常量url=”file:///Users/sam.gajjar/SG/Projects/headless-chrome/sample.html";
常量日志=(()=>{
设logId=0;
return(…args)=>console.log(logId++,…args);
})();
让浏览器;
(异步()=>{
browser=wait puppeter.launch({
无头:错,
slowMo:500,
});
const[page]=wait browser.pages();
等待页面。转到(url);
//显示起始位置
log(page.url());//0 sample.html
//单击“普通”链接并弹出带有goBack的浏览器堆栈
等待承诺([
page.waitForNavigation(),
第页。单击(“第1个子项”),
]);
log(page.url());//1 example.com
等待page.goBack();
log(page.url());//2 sample.html
//火灾位置。替换为单击
等待承诺([
page.waitForNavigation(),
页面。单击(“a:n子项(2)”,//推送历史记录(!)
]);
log(page.url());//3 example.com
等待page.goBack();
log(page.url());//4 sample.html
//火灾位置。替换为评估
等待承诺([
page.waitForNavigation(),
evaluate(()=>replaceLocation()),//不推送历史记录
]);
log(page.url());//5 example.com
等待page.goBack();
log(page.url());//6关于:blank setLocation(),//与page.click的行为相同
]);
log(page.url());//8 example.com
等待page.goBack();
log(page.url());//9 sample.html
})()
.catch(err=>console.error(err))
.finally(异步()=>等待browser.close())
;
@ggorlen-添加了Puppeter代码,其中对HTML标记的调用和内联JS函数中的调用可以工作,但外部JS中的相同函数不工作。Puppeter代码将使用HTML调用Link,然后返回并调用内联JS函数,然后返回并在失败时调用extJS函数。因此,这很有效,非常感谢。然而,我通过创建sample.html和外部JS文件简化了实际情况。。但这并不适用于实际情况。我与一个20岁的电子商务网站工作,这里是我在页面中的实际链接。现在是问题。。如果有多个外部JS,并且此链接位于嵌套的帧集中(6层深的帧),这是否重要?什么不起作用?如果你提出一个新问题,代码完全失败,我可以试着帮你。做一个简单的例子是好的,但是如果这个例子有污染/混乱的行为,比如location.replace
borkinggoBack
逻辑,而这不是你的原始意图,那么这个例子离你的原始场景太远了。再次,请打开一个新问题并包含所有相关细节。所有这些细节,比如6层框架,都是重要的信息,与您在这里展示的内容有根本的不同。是的,我同意,但在真实场景中,我不需要使用goBack(),只是在简化场景中,所有链接都在sample.html中,并希望使用jsp显示链接的变化行为,这很好,但事实证明,goBack
/location.replace
的东西无意中产生了一系列新的(但有趣的)问题,这些问题与您现在描述的问题无关。我以为这是你真正的用例。
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();
const replaceLocation = () => location.replace("https://www.example.com");
const setLocation = () => location = "https://www.example.com";
<!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>
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())
;