简体   繁体   English

将 jQuery 注入 Puppeteer 页面

[英]Inject jQuery into Puppeteer page

I'm trying to inject jQuery into my Puppeteer page because document.querySelector doesn't cut it for me:我正在尝试将 jQuery 注入到我的 Puppeteer 页面中,因为document.querySelector不适合我:

async function inject_jquery(page){
  await page.evaluate(() => {
    var jq = document.createElement("script")
    jq.src = "https://code.jquery.com/jquery-3.2.1.min.js"
    document.querySelector("head").appendChild(jq)
  })
  const watchDog = page.waitForFunction('window.jQuery !== undefined');
  await watchDog;
}

The result is it mostly times out.结果是它主要超时。 Does anyone have a solution?有没有人有解决方案?

I have used page.addScriptTag to inject js files.我使用page.addScriptTag来注入js文件。

...
await page.addScriptTag({url: 'https://code.jquery.com/jquery-3.2.1.min.js'})
...

page.addScriptTag - documentation page.addScriptTag - 文档

Working example using puppeteer: 0.12.0使用puppeteer: 0.12.0工作示例puppeteer: 0.12.0

import { launch } from 'puppeteer'
(async () => {
    const browser = await launch({headless: false});
    const page = await browser.newPage();
    await page.goto('https://example.com', {waitUntil: 'networkidle'});
    await page.addScriptTag({url: 'https://code.jquery.com/jquery-3.2.1.min.js'});
    await page.close();
    await browser.close();
})();

对于那些希望注入本地 jQuery 副本的人:

await page.addScriptTag({path: require.resolve('jquery')})

I am doing this:我正在这样做:

await page.addScriptTag({ url: 'https://code.jquery.com/jquery-3.2.1.min.js' });
const title = await page.evaluate(() => {
  const $ = window.$; //otherwise the transpiler will rename it and won't work
  return $('h1 > span').text();
});

This works for me.这对我有用。

async function inject_jquery(page){
      await page.evaluate(() => {
        var jq = document.createElement("script")
        jq.setAttribute('type','text/javascript');
        jq.src = "https://code.jquery.com/jquery-3.2.1.min.js"
        return new Promise( (resolve) => {
            jq.addEventListener("load", ()=> {
                resolve();
            });
            document.getElementsByTagName("head")[0].appendChild(jq);
        });
      })
      const watchDog = page.waitForFunction('window.jQuery !== undefined');
      await watchDog;
    }

Some sites won't allow you to inject a script tag, so you'll have to inject the contents of it before it'll allow you to do so.某些站点不允许您注入脚本标记,因此您必须先注入它的内容,然后才能允许您这样做。 If that's the case you can use the evaluate method to grab the scripts contents from a CDN and inject them manually:如果是这种情况,您可以使用evaluate方法从 CDN 中获取脚本内容并手动注入它们:

const jquery = await page.evaluate(() => window.fetch('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js').then((res) => res.text()));
await page.goto(YOUR_PAGE_HERE);
await page.evaluate(jquery);

This is used in scraping puppeteer's docs for browserless here (I'm the author of this tool) if you'd like to see an example in the wild.如果您想在野外看到一个示例,这用于在此处为无浏览器抓取puppeteer的文档(我是此工具的作者)。

The best solution found so far, URL insertion may not work due to browser origin policies, so we insert local file contents instead of URL.目前找到的最佳解决方案,由于浏览器来源策略,URL 插入可能不起作用,因此我们插入本地文件内容而不是 URL。

const fs = require('fs');
const path = require('path');

const addJQueryToPage = async (page) => {
    const file = fs.readFileSync(path.resolve(__dirname, 'jquery-file-in-same-directory.min.js'), 'utf8');
    await page.addScriptTag({ content: file });
    await page.evaluate(_ => {
        $.noConflict();
    });
}

To inject jQuery from CDN (inspired by @browserless answer above):从 CDN 注入 jQuery(灵感来自上面@browserless 的回答):

// go to page
await page.goto(url_str);
        
// inject jQuery
var jquery_ev_fn = await page.evaluate(function(){
    return window.fetch('https://code.jquery.com/jquery-3.4.1.min.js').then(function(res){
        return res.text();
    });
});
await page.evaluate(jquery_ev_fn);

To inject local jQuery:注入本地 jQuery:

// get local jQuery and inject it
var jquery_code_str = fs.readFileSync('/path/to/local/jquery.js', 'utf8');

// go to page
await page.goto(url_str);
        
// inject jQuery
var jquery_ev_fn = await page.evaluate(function(code_str){
    return code_str;
}, jquery_code_str);
await page.evaluate(jquery_ev_fn);

I had just publish my puppeteer jquery integration here我刚刚在这里发布了我的 puppeteer jquery 集成

code sample:代码示例:

let browser = await launch({headless: true});
let pageOrg = await browser.newPage();
let page = pageExtand(pageOrg);
// append a <H1>
await page.jQuery('body').append(`<h1>Title</h1>`);
// get the H1 value
let title = await page.jQuery('h1').text();
// chain calls
let text = await page.jQuery('body button:last')
          .closest('div')
          .find('h3')
          .css('color', 'yellow')
          .parent()
          .find(':last')
          .text();

Not all jQuery function are mapped yet, so open issue if you need some more function (Each call need to be add by name and with the number of parameter they take).并非所有 jQuery 函数都已映射,因此如果您需要更多函数,请打开问题(每个调用都需要按名称和它们采用的参数数量添加)。

It becomes more easier to manage if you inject your script into the your html page header if you have got like this如果您像这样将脚本注入到 html 页面标题中,则管理起来会更容易

<script type="text/javascript" src="abc.min.js"></script>

and now you can easily call its function in your page.evaluate(function(){ })现在你可以在你的页面中轻松调用它的函数。evaluate(function(){ })

You can use the following method to add jQuery to the page using page.evaluate() :您可以使用以下方法使用page.evaluate()将 jQuery 添加到页面:

await page.evaluate(async () => {
  const script = document.createElement('script');
  script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js';
  const promise = new Promise((resolve, reject) => {
    script.onload = resolve;
    script.onerror = reject;
  });
  document.head.appendChild(script);
  await promise;
});

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

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