Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/480.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Puppeter从外部.js文件调用javascript函数_Javascript_Puppeteer - Fatal编程技术网

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

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

任何人都知道如何puppeter调用javascript函数,该函数不是内联的,而是在external.js文件中。如果它在html->head->script标记中内联,则可以工作,但如果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>
木偶演员代码示例

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
borking
goBack
逻辑,而这不是你的原始意图,那么这个例子离你的原始场景太远了。再次,请打开一个新问题并包含所有相关细节。所有这些细节,比如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())
;