繁体   English   中英

如何在执行页内脚本之前操作DOM?

[英]How to manipulate the DOM before in-page scripts are executed?

使用Puppeteer ,在执行页内JS之前,如何在页面上下文中运行完整DOM的脚本?

例如,在运行任何页面JS之前,如何运行以下脚本从img元素中删除alt属性?

document.querySelectorAll('img[alt]').forEach(
  e => e.removeAttribute('alt')
)

page.evaluateOnNewDocument看起来很有用,但它似乎是在页面内容可用之前执行的 - 在它运行的时候,页面是空白的。)

我认为实现目标的方法是执行:

  1. set page.setJavaScriptEnabled(false)
  2. 进入页面
  3. 在没有脚本的情况下提取所有脚本和HTML
  4. set page.setJavaScriptEnabled(true)
  5. 使用步骤3中的HTML输入page.goto(`data:text/html,${HTMLWithoutScript}`)
  6. 执行你的脚本
  7. 从步骤3中提取原始提取的脚本page.addScriptTag({ content: script })

以下是您的问题示例的可视化:

const puppeteer = require('puppeteer');

const html = `
<html>
    <head></head>
    <body>
        <img src="https://picsum.photos/200/300?image=1062" alt="dog ">
        <img src="https://picsum.photos/200/300?image=1072" alt="car ">
        <div class="alts">List of alts: </div>
        <script>
            const images = document.querySelectorAll('img');
            const altsContainer = document.querySelector('.alts');
            images.forEach(image => {
                const alt = image.getAttribute('alt') || 'missing alt ';
                altsContainer.insertAdjacentHTML('beforeend', alt);
            })
        </script>
    </body>
</html>`;

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(`data:text/html,${html}`);
    await page.evaluate(() => {
        document.querySelectorAll('img[alt]').forEach(
            e => e.removeAttribute('alt')
        )
    });
    await page.screenshot({ path: 'image.png' });
    await browser.close();
})();

这段代码产生:

破碎的例子

所以删除alts在这里不起作用。

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    await page.setJavaScriptEnabled(false);
    await page.goto(`data:text/html,${html}`);
    const { script, HTMLWithoutScript } = await page.evaluate(() => {
        const script = document.querySelector('script').innerHTML;
        document.querySelector('script').innerHTML = '';
        const HTMLWithoutScript = document.body.innerHTML;
        return { script, HTMLWithoutScript }
    });

    await page.setJavaScriptEnabled(true);
    await page.goto(`data:text/html,${HTMLWithoutScript}`);
    await page.evaluate(() => {
        document.querySelectorAll('img[alt]').forEach(
            e => e.removeAttribute('alt')
        )
    });
    await page.addScriptTag({ content: script });
    await page.screenshot({ path: 'image.png' });
    await browser.close();
})();

这将产生您在问题中所期望的结果:

工作实例

您可以将脚本标记移动到body而不是head。 然后使用document onload事件,您可以执行脚本。 根据MDN,此事件在加载对象时触发。 下面是示例代码

 function removeAlt(){ document.querySelectorAll('img[alt]').forEach((e)=>{ e.removeAttribute('alt'); }); } 
 <body onload="removeAlt()"> <img src="http://placehold.it/64x64" alt="1"> <img src="http://placehold.it/64x64" alt="2"> </body> 

让我知道这是否符合您的要求,我测试和功能是从图像中删除alt标签

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM