Как загрузить скрипт в puppeteer?

Я пытаюсь загрузить axios в хром с помощью puppeteer, код выглядит следующим образом:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({headless:false})
  const page = await browser.newPage()
  await page.goto('https://httpbin.org/get')
  await page.evaluate(async () => {
    var script = document.createElement('script');
    script.setAttribute('src','https://unpkg.com/[email protected]/dist/axios.min.js');
    document.head.appendChild(script);
    var r = await axios.get('https://httpbin.org/get')
    console.info(r)
  })
})()

Но когда я пытаюсь выполнить axios.get, он возвращает Evaluation failed: ReferenceError: axios is not defined. В чем проблема?

🤔 А знаете ли вы, что...
С JavaScript можно создавать расширения для различных платформ, таких как Adobe Acrobat и Microsoft Office.


4
4 891
3

Ответы:

Решено

Используйте для этого page.addScriptTag:

await page.goto('https://example.com');

await page.addScriptTag({ url: 'https://unpkg.com/[email protected]/dist/axios.min.js' }); 

const data = await page.evaluate(async () => {
  const response = await axios.get('https://httpbin.org/get')
  return response.data; // <-- this is important: the whole response cannot be returned
});

page.addScriptTag полезен в общем случае, но если у вас есть причина сделать это вручную в контексте браузера, когда пытается OP, недостающая часть устанавливает функцию script.onload только для запуска кода из скрипта (например, axios.get) после того, как он загружен.

Если вы хотите вернуть данные из функции onload обратно в Node, вы можете использовать обещание следующим образом:

const puppeteer = require("puppeteer");

let browser;
(async () => {
  browser = await puppeteer.launch({headless: true});
  const [page] = await browser.pages();
  const result = await page.evaluate(async () => {
    var script = document.createElement("script");
    const result = new Promise(resolve =>
      script.onload = () => 
        resolve(axios.get("https://httpbin.org/get"))
    );
    var url = "https://unpkg.com/[email protected]/dist/axios.min.js";
    script.setAttribute("src", url);
    document.head.appendChild(script);
    return (await result).data;
  });
  console.info(result);
})()
  .catch(err => console.error(err))
  .finally(async () => await browser?.close())
;

В моем случае я пытался загрузить локальный скрипт перед загрузкой локального HTML-шаблона.

Я не хотел встраивать код скрипта в HTML-шаблон, так как HTML-шаблон уже был слишком большим.

Следующий код и локальный файл js с кодом скрипта (scriptCode.js) находились в одном каталоге (отсюда и использование __dirname):

const path = require("path");
// ...
const page = await browser.newPage();
await page.addScriptTag({path: path.join(__dirname, 'scriptCode.js')})
await page.setContent(html);

Если у вас есть axios в локальной папке, вы должны указать путь, по которому вы его скачали.

Но если вы все еще хотите каждый раз загружать его с CDN, вместо использования опции path, ответ, предоставленный Vaviloff, является идеальным.

Документация: