Как однозначно идентифицировать экземпляры браузера puppeteer?

#node.js #express #puppeteer

Вопрос:

Я разрабатываю API автоматизации в Node.js с кукловодом. Когда API вызывается, создается экземпляр браузера без головы кукловода, и запускается какой-то процесс автоматизации, такой как вход в систему, и он входит в профиль пользователя, переданный при вызове. Но если веб — сайт, на котором я выполняю автоматизацию, обнаруживает поведение бота. Он отправляет код входа в систему по электронной почте, поэтому отправляется ответ на этот вызов API с запросом кода входа. Когда код входа отправляется в другом вызове API, он просто переходит на эту страницу и помещает код. Следовательно, мы входим в систему. Эта штука отлично работает, когда у меня есть только один экземпляр браузера. Но когда запущено несколько экземпляров браузера, API кода входа не получает требуемую страницу. Он переходит к последнему созданному экземпляру браузера, который может выполнять какой-либо другой процесс вместо целевого экземпляра, где требуется код входа.

Здесь мой вопрос заключается в том, как я могу однозначно идентифицировать экземпляры браузера, чтобы я мог ввести код входа в этот экземпляр вместо какого-либо другого экземпляра, выполняющего другой процесс для другого пользователя.

Запустите браузер

 let browser;  let page;  async function startBrowser() {   if(proxyUrl == '' || proxyUn == '' || proxyPw == ''){  browser = await puppeteer.launch({   //slowMo: 30, // to slowdown the process   headless: false, // set as false to open a chromium    ignoreDefaultArgs: ["--enable-automation"],    defaultViewport: null,    args: ["--no-sandbox",    "--disable-setuid-sandbox",    "--start-maximized",    '--window-size=1920,1080',    "--disable-gpu",    "--disable-dev-profile",    ]    });   }else{   //proxy Chain for proxy application    const oldProxyUrl = `http://${proxyUn}:${proxyPw}@${proxyUrl}`;   const newProxyUrl = await proxyChain.anonymizeProxy(oldProxyUrl);   browser = await puppeteer.launch({   //slowMo: 30, // to slowdown the process    headless: false, // set as false to open a chromium    ignoreDefaultArgs: ["--enable-automation"],    defaultViewport: null,    args: ["--no-sandbox",    "--disable-setuid-sandbox",    "--start-maximized",    '--window-size=1920,1080',    "--disable-gpu",    "--disable-dev-profile",    `--proxy-server=${newProxyUrl}`,    ]    });       }   browser.on('disconnected', function(){  browser = '';  });   page = await browser.newPage();   await page.setViewport({ width: 1920, height: 1080 });   page.setUserAgent(   "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"   );  }  

Игровой тест

 async function playTest(url, res) {   try {  try{   await startBrowser();   await page.setDefaultNavigationTimeout(32400000);    }catch(e){   proxyFailedFlag = true;   console.error(new Date().toLocaleString()   ': ', e);   return res.status(400).json({ status: 'failure', info: 'Invalid Proxy' }).end();    }   try{   console.log(new Date().toLocaleString()   ': ', 'connecting login page ...');    await page.goto(url);   }catch(e){   proxyFailedFlag = true;   await closeBrowser(browser);   console.error(new Date().toLocaleString()   ': ', e);   return res.status(400).json({ status: 'failure', info: 'Invalid Proxy' }).end();    }   await waitTillHTMLRendered(page);   await page.setViewport({   width: 1400,   height: 966   });   await playing(res);   } catch (e) {   console.error(new Date().toLocaleString()   ': ', e);    }  }  

Playing

 const playing = async (res) =gt; {   console.log(new Date().toLocaleString()   ': ', 'waiting for login form ...');   if (await page.$(ACCEPT_COOKIES_SELECTOR) !== null) {   const accept_elm = await page.$(ACCEPT_COOKIES_SELECTOR);   await accept_elm.click({ clickCount: 1 });   }   await page.waitForSelector(USERNAME_SELECTOR, {   visible: true,   });     await page.click(USERNAME_SELECTOR);   await page.keyboard.type(email);   await page.click(PASSWORD_SELECTOR);   await page.keyboard.type(password);    const m_login_elm = await page.$(M_LOGIN_SELECTOR);   await m_login_elm.click({ clickCount: 1 });    console.log(new Date().toLocaleString()   ': ', 'logging in ...');    try {   await page.waitForNavigation();   let pageURL = page.url();   console.log("page url: ", pageURL)   if (pageURL === 'https://www.targetwebsite.com/feed/') {   loginFailedFlag = false;   let accountElm = await page.$(PROFILE_NAME_SELECTOR);   accountName = await page.evaluate(accountElm =gt; accountElm.textContent, accountElm);   accountName = accountName.trim();   console.log("Login success", accountName);   } else if (pageURL === "https:/www.targetwebsite.com/login-submit") {   console.log("Exception Login Submit Form!");   if (await page.$(NOT_REMEMBER_BTN_SELECTOR) !== null) {   const notRememberBtn = await page.$(NOT_REMEMBER_BTN_SELECTOR);   await notRememberBtn.click({ clickCount: 1 });    } else {   throw new Error('Login fail!');   }   } else {   pageURL = pageURL.split("challenge");   if(pageURL[0]==="https://www.targetwebsite.com/captcha/"){   loginFailedFlag = true;   return res.status(400).json({ status: 'failure', info: 'Captcha' }).end();   }   loginFailedFlag = false;   console.log("Pin code is required");   }    } catch (error) {  loginFailedFlag = true;  return res.status(400).json({ status: 'failure', info: 'Invalid Login' }).end();  }     if (await page.$(PIN_INPUT_SELECTOR) !== null) {     console.log("pin code required")   warnFlag = true   warnmsg = 'Awaiting IP Code';   } else {     warnFlag = false   console.log('not found Pin Code step');   await waitTillHTMLRendered(page);   if (await page.$(RE_ACCEPT_COOKIES_SELECTOR) !== null) {   const accept_elm = await page.$(RE_ACCEPT_COOKIES_SELECTOR);   await accept_elm.click({ clickCount: 1 });   }   await getCookies();   }  }  

Когда код для входа будет отправлен во втором вызове API

 async function handleIpProcess(ip_email, ip_code) {   await waitTillHTMLRendered(page);   await page.click(PIN_INPUT_SELECTOR);   await page.keyboard.type(ip_code);    await page.waitForSelector(PIN_SUBMIT_SELECTOR, {    visible: true,    });    await page.click(PIN_SUBMIT_SELECTOR);    await getCookies();  }  

Ответ №1:

Я решил эту проблему, создав объект для каждого экземпляра с идентификатором uuid и поместив его в массив.

 browser = {  uuid: email, //used email because it was most suitable in my case  pass: password,  instance: undefined,  page: undefined }  browserInstances.push(browser); //browserInstances is an array initialized earlier in the code