用 Python + Selenium + Browser Driver 实现华为手机自动抢购

随着华为手机的火爆,每次发售的时候,许多小伙伴都会面临“秒没”的困扰。为了提升抢购的成功率,我们可以用 Python 来写一个自动化抢购脚本,利用 Selenium 模拟用户操作,大大提高抢购成功的几率。

本文将详细介绍如何使用 Python + Selenium + 浏览器驱动 来编写一个华为手机自动抢购的脚本。

一、准备工作
  1. Python 环境安装

    首先,你需要安装 Python。可以在 Python官网 下载并安装适合你操作系统的版本。安装完成后,可以在命令行中输入以下命令来确认是否安装成功:

    python --version
    

    输出 Python 版本号表示安装成功。

  2. 安装 Selenium

    Selenium 是一个自动化测试工具,能够控制浏览器进行各种操作。使用 pip 来安装 Selenium:

    pip install selenium
    
  3. 浏览器驱动

    Selenium 需要依赖浏览器驱动与真实的浏览器进行交互。这里我们选择Chrome的驱动。以下是主流浏览器的驱动下载地址:

    • Chrome驱动下载:https://sites.google.com/chromium.org/driver/downloads

    下载对应的驱动后,将其路径添加到系统的环境变量中或者在程序中指定路径,确保 Selenium 能够找到它。

二、脚本代码

接下来,我们将使用 Python + Selenium 编写一个简单的华为手机抢购脚本。脚本的核心流程包括:

  • 打开华为商城
self.browser.get('https://www.vmall.com/')
self.driverWait.until(EC.url_changes)
  • 登录账号
    def __do_login(self):
        logger.info("开始输入账号及密码")
        inputElements = self.driverWait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, "hwid-input")))

        inputElements[0].send_keys(self.config.get("user", "name"))
        inputElements[1].send_keys(self.config.get("user", "password"))
        logger.info("已输入账号及密码")

        self.driverWait.until(EC.presence_of_element_located((By.CLASS_NAME, "hwid-login-btn"))).click()
        logger.info("发起登录请求")
  • 进入商品页面
    def __visit_product_page(self):
        currentUrl = self.browser.current_url
        logger.info("开始进入华为 {0} 产品详情页".format(self.config.get("product", "name")))
        self.browser.get("https://www.vmall.com/product/{0}.html".format(self.config.get("product", "id")))
        try:
            self.driverWait.until(EC.url_changes(currentUrl))
            logger.info("已进入华为 {0} 产品详情页".format(self.config.get("product", "name")))
            self.__get_current_page_type()
        except TimeoutException:
            logger.info("进入华为 {0} 产品详情页失败,程序将在3秒后退出...".format(self.config.get("product", "name")))
            time.sleep(3)
            self.browser.quit()
    def __choose_product_item(self):
        logger.info("开始选择手机单品规格")
        sku_color = self.config.get("product", "color")
        sku_version = self.config.get("product", "version")
        self.driverWait.until(EC.presence_of_element_located((By.XPATH, f"//div[text()='{sku_color}']"))).click()
        self.driverWait.until(EC.presence_of_element_located((By.XPATH, f"//div[text()='{sku_version}']"))).click()
        sku_payment = '无'
        # if EC.text_to_be_present_in_element((By.XPATH, "//div[text()='销售类型']"), "销售类型")(self.browser):
        #     sku_payment = self.config.get("product", "payment")
        #     self.driverWait.until(EC.presence_of_element_located((By.XPATH, f"//div[text()='{sku_payment}']"))).click()
        logger.info("选择手机单品规格完成,颜色:{0} 版本:{1} 销售类型:{1}".format(sku_color, sku_version, sku_payment))
  • 判断是否可以购买
    def __waiting_count(self):
        times = 1
        while self.isWaiting and times <= 3:
            try:
                if EC.text_to_be_present_in_element((By.XPATH, "//div[text()='立即购买']"), "立即购买")(
                        self.browser):
                    logger.info("当前可立即下单")
                    self.__set_end_countdown()
                    self.__set_buy_now()
                elif EC.text_to_be_present_in_element((By.XPATH, "//div[text()='暂时缺货']"), "暂时缺货")(
                        self.browser):
                    logger.info("【{}】倒计时未开始,等待中...", "暂时缺货")
                    time.sleep(120)
                    self.__refresh_product_page()
                elif EC.text_to_be_present_in_element((By.XPATH, "//div[text()='即将开始']"), "即将开始")(
                        self.browser):
                    logger.info("倒计时即将开始")
                    self.__get_sec_kill_time()
                    if self.secKillTime is not None:
                        self.__set_end_waiting()
                        time.sleep(1)
                else:
                    logger.info("【{}】倒计时未开始,等待中...", "暂不售卖")
                    time.sleep(120)
                    self.__refresh_product_page()
            except NoSuchElementException:
                time.sleep(1)
                times += 1
  • 下单
    def __start_buying(self):
        logger.info("进入抢购活动最后排队下单环节")
        self.__create_and_start_thread()
        clickTimes = 1
        while self.isStartBuying:
            countdownMsDiff = utils.calc_countdown_ms_diff(self.secKillTime,
                                                           self.localTimestamp - self.hwServerTimestamp)
            countdown_times = utils.calc_countdown_times(self.secKillTime,
                                                         self.localTimestamp - self.hwServerTimestamp)
            if countdownMsDiff > 1000:
                logger.info("距离抢购活动最后下单环节开始还剩:{}", utils.format_countdown_time(countdown_times))
                time.sleep(1)
            elif countdownMsDiff > 100:
                logger.info("距离抢购活动最后下单环节开始还剩:{}", utils.format_countdown_time(countdown_times))
                time.sleep(0.1)
            elif countdownMsDiff > 10:
                logger.info("距离抢购活动最后下单环节开始还剩:{}", utils.format_countdown_time(countdown_times))
                time.sleep(0.01)
            else:
                logger.info("抢购活动最后下单环节,进行第 {} 次尝试立即下单", clickTimes)
                self.__do_start_buying()
                self.__check_can_submit_order()
                self.__submit_order()
                clickTimes += 1
                time.sleep(float(self.config.get('process', 'interval', '0.001')))
 
   def __buy_now(self):
        if self.isBuyNow:
            currentUrl = self.browser.current_url
            logger.info("开始立即购买")
            try:
                buttons = self.driverWait.until(
                    EC.presence_of_all_elements_located((By.XPATH, "//div[text()='立即购买']")))
                orderBtn = None
                for button in buttons:
                    if '立即购买' == button.text:
                        orderBtn = button
                if orderBtn is not None:
                    orderBtn.click()
                    time.sleep(1)

                    new_window = self.browser.window_handles[-1]
                    self.browser.switch_to.window(new_window)
                    self.__click_submit_order(currentUrl)
            except (NoSuchElementException, ElementClickInterceptedException, StaleElementReferenceException) as e:
                logger.info("未找到【立即购买】按钮或按钮不可点击; except:{}", e)
            logger.info("结束立即购买")
三、运行脚本

程序运行效果

用 Python + Selenium + Browser Driver 实现华为手机自动抢购

上一篇:autogen改变屏幕亮度


下一篇:【C++】多态练习题(面试常考)