Création d'un bot pour acheter sur un site internet

Fermé
Wyrmand Messages postés 1 Date d'inscription samedi 15 février 2020 Statut Membre Dernière intervention 15 février 2020 - Modifié le 15 févr. 2020 à 16:40
 DevGnode - 7 mars 2020 à 19:34
Bonjour,
J'ai récupéré un programme. Il s'agit d'un bot pour acheter sur le site nike mais je n'arrive pas à le configurer afin qu'il ajoute l'article souhaiter dans mon panier.
Le lien pour le dossier complet : https://github.com/tylerburleigh/nike-buy-bot
Voici le code:
const puppeteer = require('puppeteer-extra');
const pluginStealth = require("puppeteer-extra-plugin-stealth");
const fs = require('fs');
const {installMouseHelper} = require('./extras/install_mouse_helper');
puppeteer.use(pluginStealth())

// Debugging stuff
const html_path = 'htmls/bot_';
const screenshot_path = 'screenshots/bot_';
const SimpleNodeLogger = require('simple-node-logger'),
 opts = {
  logFilePath: 'logs/' + 'bot.log',
  timestampFormat:'YYYY-MM-DD HH:mm:ss.SSS'
 };
let html = '';


// ####################################
// ####################################
// Parameters to set

// user/pass: the email/username for your Nike.com account
const user = 'myname@gmail.com';
const pass = 'mypassword';

// cv_code: 3-digit credit card validation code for the card saved to your Nike.com account
const cv_code = '123';

// size: the shoe size, as you see in the table of sizes on a product page, e.g., 'M 9 / W 10.5'
const size = 'EU 40';

// url: url to the shoe page, e.g., 'https://www.nike.com/us/launch/t/kobe-4-protro-wizenard/'
const url = 'https://www.nike.com/fr/launch/t/react-vision-gravity-purple/';

// debug: Use debug/logging features?
// Includes writing updates to log file, writing html snapshots, and taking screenshots
const debug = true;

// buy: ****WARNING**** if you set this to true it *may* actually make a purchase
// you can leave this to false and the bot will not "submit order"
const buy = false;





// ####################################
// ####################################
// main flow
(async () => { 

 const browser = await puppeteer.launch({
  ignoreHTTPSErrors: true,
  headless: false
 });

 const page = await browser.newPage();
 
 if(debug == true){ 
  await installMouseHelper(page); // Makes mouse visible
  
  var dir = './htmls';
  if (!fs.existsSync(dir)){
   fs.mkdirSync(dir);
  }
  dir = './screenshots';
  if (!fs.existsSync(dir)){
   fs.mkdirSync(dir);
  }
  dir = './logs';
  if (!fs.existsSync(dir)){
   fs.mkdirSync(dir);
  }
  
  log = SimpleNodeLogger.createSimpleFileLogger( opts );
  log.setLevel('info'); 
  
 }
  
 await page.goto(url);
 page.waitForNavigation({ waitUntil: 'networkidle0' }); // Wait for page to finish loading
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 1
 // BEGIN
 
 // #### LOG / DEBUG
 if(debug == true){ 
  log.info('1. Page loaded'); 
  html = await page.content();
  fs.writeFileSync(html_path + "_1_loaded_" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_1_loaded_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500);
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 2 
 // Wait for size selector to appear, then scroll to it
 
 await page.waitForSelector('.size-grid-dropdown');
 await page.evaluate(() =>
  document.querySelectorAll(".size-grid-dropdown")[0].scrollIntoView()
 );
 
 // #### LOG / DEBUG
 if(debug == true){ 
  log.info('2. Selectors appeared'); 
  html = await page.content();
  fs.writeFileSync(html_path + "_2_selectors_" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_2_selectors_" + Math.floor(new Date() / 1000) + '.png'}); 
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500);
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 3
 // Pick my size from the options
 
 await page.evaluate(async(size) => {
  let sizes = await Array.from(document.querySelectorAll(".size-grid-dropdown"));
  let sizeIndex = sizes
   .map((s, i) => (s.innerHTML === size ? i : false))
   .filter(Boolean)[0];
  return sizes[sizeIndex].click();
 }, size);
 
 
 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('3. Found and clicked on size');
  html = await page.content();
  fs.writeFileSync(html_path + "_3_size_clicked__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_3_size_clicked_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500);
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 4 
 // Wait for add to cart button, then scroll into view
 
 await page.waitForSelector('button[data-qa=feed-buy-cta]');
 await page.evaluate(() =>
  document.querySelectorAll("button[data-qa=feed-buy-cta]")[0].scrollIntoView()
 );
 
 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('4. Scrolled to add button');
  html = await page.content();
  fs.writeFileSync(html_path + "_4_scroll_to_add_button__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_4_scroll_to_add_button_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500);
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 5 
 // Click the add to cart button
 
 await page.evaluate(() =>
  document.querySelectorAll("button[data-qa=feed-buy-cta]")[0].click()
 );

 
 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('5. Clicked add button');
  html = await page.content();
  fs.writeFileSync(html_path + "_5_clicked_add_button__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_5_clicked_add_button_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500); 
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 6
 // Login
 
 await page.waitForSelector('.emailAddress');
 await page.waitFor(500);
 
 // Username
 await page.focus('.emailAddress > input');
 await page.keyboard.type(user);
 await page.waitFor(200);
 
 // Password
 await page.focus('.password > input')
 await page.keyboard.type(pass);
 await page.waitFor(200);
 
 // Submit
 await page.evaluate(() =>
  document.querySelectorAll(".loginSubmit > input")[0].click()
 ); 

 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('6. Logged in');
  html = await page.content();
  fs.writeFileSync(html_path + "_6_logged_in__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_6_logged_in_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500); 
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 7
 // Enter credit card info
 
 await page.waitForSelector('.credit-card-iframe');
 await page.waitForSelector('.credit-card-iframe');
 
 await page.evaluate(() =>
  document.querySelectorAll(".credit-card-iframe")[0].scrollIntoView()
 );
 await page.waitFor(200);
 
 const target_frame = page.frames().find(frame => frame.url().includes('paymentcc.nike.com'));
 
 await target_frame.evaluate(
  () => (document.getElementById("cvNumber").focus())
 ); 
 await target_frame.waitFor(1000);
 await page.keyboard.type(cv_code, {delay: 10});
 
 
 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('7. Entered CV');
  html = await page.content();
  fs.writeFileSync(html_path + "_7_entered_cv__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_7_entered_cv_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500); 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 8
 // Click "Save & Continue"
 
 await page.waitForSelector('.save-button');
 const buttons = await page.$$('.save-button');

 await buttons[1].click(); 
 
 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('8. Clicked Save & Continue');
  html = await page.content();
  fs.writeFileSync(html_path + "_8_save_continue__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_8_save_continue_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500);  
 
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 9
 // Click "Submit Order"
 
 if(buy == true){
  await buttons[2].click();
  
  //#### LOG / DEBUG
  if(debug == true){ 
   log.info('9. Submitted Order');
   html = await page.content();
   fs.writeFileSync(html_path + "_9_submitted_order__" + Math.floor(new Date() / 1000) + ".html", html);
   page.screenshot({path: screenshot_path + "_9_submitted_order_" + Math.floor(new Date() / 1000) + '.png'});
  }
  //#### LOG / DEBUG END
  
  await page.waitFor(500);
  
 }
 
 
 
 
 //await browser.close();
})();

Mon problème ce situe ici :
// Wait for add to cart button, then scroll into view
 
 await page.waitForSelector('button[data-qa=feed-buy-cta]');
 await page.evaluate(() =>
  document.querySelectorAll("button[data-qa=feed-buy-cta]")[0].scrollIntoView()
 );
 
 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('4. Scrolled to add button');
  html = await page.content();
  fs.writeFileSync(html_path + "_4_scroll_to_add_button__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_4_scroll_to_add_button_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500);
 
 
 
 
 // ##################################################
 // ##################################################
 // ################################## ROUND 5 
 // Click the add to cart button
 
 await page.evaluate(() =>
  document.querySelectorAll("button[data-qa=feed-buy-cta]")[0].click()
 );

 
 //#### LOG / DEBUG
 if(debug == true){ 
  log.info('5. Clicked add button');
  html = await page.content();
  fs.writeFileSync(html_path + "_5_clicked_add_button__" + Math.floor(new Date() / 1000) + ".html", html);
  page.screenshot({path: screenshot_path + "_5_clicked_add_button_" + Math.floor(new Date() / 1000) + '.png'});
 }
 //#### LOG / DEBUG END
 
 await page.waitFor(500);


Pouvez-vous m'aider!!SVP!! Pour me répondre, soit à la suite de ce message soit par mail : ****@*****.**

EDIT : Ajout des balises de code (la coloration syntaxique).
Explications disponibles ici : ICI

Merci d'y penser dans tes prochains messages.

1 réponse

Au lieu de récupérer des bouts de code que tu ne comprend pas est de passer un temps possible à debbugger tu peux faire ça par toi même avec des frameworks d'automatisation front-office.

Si tu veux faire un bot, tout simplement prend le temps de lire les documentations sur les différentes frameworks automatisation comme Selenium/webDriver en Java ou nodeJs sans mode headless pour débuter.

Cypress- nodeJs
Selenium - java python c# nodeJs

Apparement puppeteer est une framwork en mode headless ( https://github.com/puppeteer/puppeteer/blob/master/README.md ) le mode headless permet de réaliser les actions sans l'ourverture en graphical user interface du webbrowser tu aura juste des logs en console si des points de verification en console y sont implémenté, check les logs généré par le script.

De plus les sites sont en constante évolution, il se peut que les différentes class ou id ou xpath afin de récupérer les éléments ont été modifié dans l'arborescence du site en question et ton code devient obsolète, des fix ou refactoring seront à faire.

Avant tous essaie de comprendre ce que tu fait.

Après je ne connais pas le mode de paiement chez nike mais si il utilise le mode SPIPS tu sera bloqué au moment payement.

Cdlt,
7