Puppeteer 模拟浏览器自动付款

在给 ChatGPT 代充 Plus 会员时,每次电脑上都是填入同样的信息,比如信用卡和地址。这个过程大概就是重复:复制链接 – 打开浏览器 – 填入信用卡 – 填入账单地址 – 点提交。我想着应该可以用 Puppeteer实现自动化操作,又因为 ChatGPT 升级 Plus 采用 Stripe 网关付款,它们做了非常严格的反爬措施,所以这里再用 Stealth 模拟更真实的浏览器行为。

下面是我的代码,因为我后面不需要这个自动化,所以没完全测试,但大致是没问题的,可以参考一二。

首先创建一个账单地址 address.js,这里我采用韩国的地区和市,我希望每次进入页面随机抽取其中一个填入,所以这是一个数组。

const addresses = [
    {
      area: '대구광역시',
      billingLocality: 'Daegu',
      billingDependentLocality: 'Daegu',
      addressLine1: '82-2, Sangyeog 2(i)-dong, Buk-gu, Daegu',
      billingPostalCode: '702-012'
    },
    {
      area: '충청북도',
      billingLocality: 'Incheon',
      billingDependentLocality: 'Incheon',
      addressLine1: '72-2, Hwasanri, Chopyeong-myeon, Jincheon-gun, Chungcheongbuk-do',
      billingPostalCode: '365-851'
    },
    {
      area: '대구광역시',
      billingLocality: 'Daegu',
      billingDependentLocality: 'Daegu',
      addressLine1: '1500-7, Sangyeog 4(sa)-dong, Buk-gu, Daegu',
      billingPostalCode: '702-843'
    },
    {
      area: '전라북도',
      billingLocality: 'Jeonju',
      billingDependentLocality: 'Jeonju',
      addressLine1: '367-10, Jungnosong-dong, Wansan-gu Jeonju-si, Jeollabuk-do',
      billingPostalCode: '560-861'
    }
  ];
  module.exports = addresses;

接着创建主程序文件 chatgpt-plus-pag.js,因为我希望一张信用卡付款失败,再次填入其他信用卡。现在主文件中添加信用卡信息

const infoList = [
    {
      cardNumber: '5205143438492643',
      cardExpiry: '0326',
      cardCvc: '817',
      billingName: 'Stacey Smith'
    }
    ,
    {
        cardNumber: '5205143802556866',
        cardExpiry: '0326',
        cardCvc: '759',
        billingName: 'Stacey Williams'
      },
  ];

安装 Puppeteer 拓展插件,才能引入使用

npm install puppeteer-extra puppeteer-extra-plugin-stealth

在主程序添加引入代码

const puppeteer = require('puppeteer-extra');
const addresses = require('./address.js');
const fs = require('fs');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin({
    screenResolution: '1680x1050', // 设置屏幕分辨率
    userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36', // 设置用户代理为 Macbook Pro
    locale: 'en-US', // 设置语言区域
  }));

我希望每次点击执行后,在本地将使用的信用卡信息和充值邮箱、时间写入到本地,当做记录,每次执行追加记录一条。

  async function saveDataToFile(page) {
    // 获取邮箱和卡号
    const email = await page.$eval('.ReadOnlyFormField-title', el => el.innerText);
    const cardNumber = await page.$eval('#cardNumber', el => el.value);
  
    // 获取当前日期时间
    const dateTime = new Date().toLocaleString();
  
    // 将数据写入文件
    fs.appendFileSync('data.txt', `${dateTime}\nEmail: ${email}\nCard Number: ${cardNumber}\n\n`);
  }

还有个特殊的地方,默认加载页面这个地址可能显示全部,也可能要手动展开。

所以我们需要判断,如果存在手动输入地址的按钮,则点击按钮并等待表单出现后手动填写地址。

OK,这里我贴出主程序完整代码。

const puppeteer = require('puppeteer-extra');
const addresses = require('./address.js');
const fs = require('fs');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin({
    screenResolution: '1680x1050', // 设置屏幕分辨率
    userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36', // 设置用户代理为 Macbook Pro
    locale: 'en-US', // 设置语言区域
  }));
  
(async () => {
  // 启动 Puppeteer
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null,
    args: [
        '--start-maximized',
        '--disable-cache',
        '--disable-application-cache'
      ],
    userDataDir: '/tmp/puppeteer_user_data'
  });

  // 创建一个新页面
  const page = await browser.newPage();

  // 访问网站
  // 读取文件内容(本地创建 url.txt )
  const url = fs.readFileSync('./url.txt', 'utf-8');
  await page.goto(url);

  for (let i = 0; i < infoList.length; i++) {
    const info = infoList[i];
  
    // 填写表单
    await page.waitForSelector('input[name="cardNumber"]', { timeout: 5000, visible: true });
    await page.type('input[name="cardNumber"]', info.cardNumber,{delay: 100});
    await page.type('input[name="cardExpiry"]', info.cardExpiry,{delay: 100});
    await page.type('input[name="cardCvc"]', info.cardCvc,{delay: 100});
    await page.type('input[name="billingName"]', info.billingName,{delay: 100});

    // 判断是否需要输入账单地址
    const addressButton = await page.$('.Text.Text-color--gray400.Text-fontSize--12.Text-fontWeight--400');
    //获取随机地址
    const randomIndex = Math.floor(Math.random() * addresses.length);
    const address = addresses[randomIndex];
    if (addressButton) {
        // 如果存在手动输入地址的按钮,则点击按钮并等待表单出现后手动填写地址
        await addressButton.click();
        await page.waitForSelector('input[name="billingPostalCode"]');
        await fillAddress(page,address);
      } else {
        // 如果不存在手动输入地址的按钮,则直接填写地址
        await fillAddress(page,address);
      }
    
    await page.waitForTimeout(1000); // 添加延迟  
    await page.waitForSelector('#termsOfServiceConsentCheckbox'); // 等待单选框加载
    await page.evaluate(() => {
    document.querySelector('#termsOfServiceConsentCheckbox').click(); // 模拟单击事件
    });

    //写入数据到本地
    saveDataToFile(page);

    // 提交表单
    await page.waitForSelector('button[type="submit"]:not([disabled])');
    await page.click('button[type="submit"]');
  }

  // 关闭浏览器
//   await browser.close();
})();

  async function fillAddress(page,address) {
    const {area, billingLocality, billingDependentLocality, addressLine1, billingPostalCode} = address;
    await page.select('#billingAdministrativeArea', area);
    await page.waitForTimeout(1000); // 添加延迟
    await page.focus('input[name="billingLocality"]');
    await page.type('input[name="billingLocality"]', billingLocality);
    await page.waitForTimeout(500); // 添加延迟
    await page.type('input[name="billingDependentLocality"]', billingDependentLocality);
    await page.waitForTimeout(500); // 添加延迟
    await page.type('input[name="billingAddressLine1"]', addressLine1 ,{delay: 100});
    await page.waitForTimeout(500); // 添加延迟
    await page.type('input[name="billingPostalCode"]', billingPostalCode ,{delay: 100});
  }

  async function saveDataToFile(page) {
    // 获取邮箱和卡号
    const email = await page.$eval('.ReadOnlyFormField-title', el => el.innerText);
    const cardNumber = await page.$eval('#cardNumber', el => el.value);
  
    // 获取当前日期时间
    const dateTime = new Date().toLocaleString();
  
    // 将数据写入文件
    fs.appendFileSync('data.txt', `${dateTime}\nEmail: ${email}\nCard Number: ${cardNumber}\n\n`);
  }
    
const infoList = [
    {
      cardNumber: '5405243438492643',
      cardExpiry: '0326',
      cardCvc: '847',
      billingName: 'Stacey Smith'
    }
    ,
    {
        cardNumber: '5405243802556866',
        cardExpiry: '0326',
        cardCvc: '759',
        billingName: 'Stacey Williams'
      },
  ];
  

OK,希望这个浏览器自动付款脚本对你有用。

本文由老郭种树原创,转载请注明:https://guozh.net/puppeter-simulates-browser-automatic-payment/

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注