淘宝“秒杀”脚本

淘宝“秒杀”脚本python+selenium实现,定时自动结算购物车,邮件提醒结果。说是秒杀脚本,但其实根本做不到毫秒级(看很多文章写毫秒级也是跪了)。自己在mac上实测,大约10s左右会收到邮件。用selenium秒杀是不要想了,用作自动提交订单,还算ok。整个流程比较简单,扫码登陆,跳转到购物车界面,不停刷新,等时间差不多到了,全选,提交订单,做个练手脚本,简单实用。通知截图:整个…

大家好,又见面了,我是你们的朋友全栈君。

python + selenium 实现,定时自动结算购物车,邮件提醒结果。

说是秒杀脚本,但其实根本做不到毫秒级(看很多文章写毫秒级也是跪了)。自己在mac上实测,大约10s左右会收到邮件。用selenium秒杀是不要想了,用作自动提交订单,还算ok。

整个流程比较简单,扫码登陆,跳转到购物车界面,不停刷新,等时间差不多到了,全选,提交订单,做个练手脚本,简单实用。

通知截图:

淘宝“秒杀”脚本

整个代码如下,邮箱相关参数读取部分懒得写全了,就这样吧。

# -*- coding: UTF-8 -*-
import argparse
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import datetime
import time
import logging
import sys
from retry import retry

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(funcName)s - %(levelname)s - %(message)s')
logger = logging.getLogger('Buyer')



class EmailInfo(object):

    def __init__(self):
        self.port = 25
        self.mail_host = 'xxxxxxxxx'
        self.mail_user = 'xxxxxxxxx'
        self.mail_pass = 'xxxxxxx'
        self.sender = 'xxxxxx'
        self.receivers = 'xxxxxxxxx'

class retryTimes():
    def __init__(self, retry_times=3):
        self.retry_times = retry_times

class BUY_MASHINE():

    def __init__(self, buy_time, max_retry=3):
        self.BUY_TIME = buy_time
        self.BUY_TIME_OBJECT = datetime.datetime.strptime(self.BUY_TIME, '%Y-%m-%d %H:%M:%S')
        self.LOG_STATUS = 0   # 未登录
        self.MAX_RETRY = max_retry
        self.TAOBAO = "https://login.taobao.com/"
        self.MAX_SUBMIT = 50
        #self.BUY_TYPE = buy_type    # 0:秒杀 1:到点改价
        self.Email = EmailInfo()


    def init(self):
        self.option = Options()
        self.option.add_argument('disable-infobars')     # 隐藏 启动浏览器出现‘Chrome正在受到自动软件的控制'
        self.option.add_argument('log-level=3')           # LOG_FATAL
        self.option.add_experimental_option('excludeSwitches', ['enable-automation'])
        # prefs = {"profile.managed_default_content_settings.images": 2}
        # self.option.add_experimental_option("prefs", prefs)
        self.driver = webdriver.Chrome(chrome_options=self.option)
        #self.driver.maximize_window()

    def switch_to_qr_load(self):
        # 点击扫码界面
        locator_qr = (By.ID, 'J_Static2Quick')
        WebDriverWait(self.driver, 30, 0.5).until(EC.presence_of_element_located(locator_qr))
        logger.info('二维码已载入')
        qr = self.driver.find_element_by_id('J_Static2Quick')
        if qr.is_displayed():
            logger.info('账号密码已显示')
            ActionChains(self.driver).move_to_element_with_offset(qr, 0, 0).click().perform()
            # ActionChains(dr).move_to_element(ma).click().perform()  # 此方法无效
            logger.info('已切换为二维码登录')


    # 请点击刷新
    # 扫描成功
    def login(self):
        logger.info("开始登陆===>>>")
        self.driver.get(self.TAOBAO)
        time.sleep(1)

        max_tries=retryTimes(self.MAX_RETRY)

        @retry(tries=self.MAX_RETRY, delay=1)
        def login_with_retry(**kargs):

            cnt = 0
            max_tries.retry_times -= 1
            for key in kargs.keys():
                kargs[key]

            while True:
                if cnt == 60:           # 1min 刷新
                    if max_tries.retry_times > 0:
                        logger.info("retrying...")
                        raise NotImplementedError('login')
                    else:
                        return False
                if self.driver.current_url != self.TAOBAO:
                    logger.info('扫描成功')
                    # page_source = self.driver.page_source
                    # logger.debug(page_source)
                    return True

                time.sleep(1)
                cnt += 1

        return login_with_retry(func1=self.driver.refresh(), func2=self.switch_to_qr_load())

    def working(self):
        self.driver.get("https://cart.taobao.com/cart.htm")
        time.sleep(1)
        self.wait()
        self.driver.get("https://cart.taobao.com/cart.htm")
        time.sleep(1)
        # 点击购物车里全选按钮
        if self.driver.find_element_by_id("J_SelectAll1"):
            self.driver.find_element_by_id("J_SelectAll1").click()
            logger.info("已经选中购物车中全部商品 ...")

        self.buying()

    def buying(self):
        max_submit = retryTimes(self.MAX_SUBMIT)
        # 60~31
        @retry(tries=-1)
        def submit_with_retry(driver):
            try:
                driver.find_element_by_link_text('提交订单').click()
                logger.info("已经点击提交订单按钮")
                return True
            except Exception as e:
                if max_submit.retry_times <= 0:
                    logger.info("提交订单失败...")
                    return False
                logger.info("没发现提交订单按钮,可能页面还没加载出来,重试...")
                raise NotImplementedError('submit')
            finally:
                max_submit.retry_times -= 1

        @retry(tries=-1)
        def buying_with_retry(driver, deadline, ending=60):
            now = datetime.datetime.now()

            if now >= self.BUY_TIME_OBJECT:
                # 点击结算按钮
                if self.driver.find_element_by_id("J_Go"):
                    self.driver.find_element_by_id("J_Go").click()
                    logger.info("已经点击结算按钮...")
                    return submit_with_retry(driver)

                if (now - deadline).seconds >= ending:
                    logger.info("Orz...buying failed at {}".format(now))
                    return False

            else:
                logger.info('finally waiting...')
                raise NotImplementedError('buying')

        ret = buying_with_retry(self.driver, self.BUY_TIME_OBJECT)
        self.sendMail(ret, datetime.datetime.now())
        return ret

    def wait(self):
        while True:
            currentTime = datetime.datetime.now()
            if (self.BUY_TIME_OBJECT - currentTime).seconds > 90:
                self.driver.refresh()
                logger.info("刷新购物车界面,防止登录超时...")
                time.sleep(60)
            else:
                logger.info("抢购时间点将近,停止自动刷新,准备进入抢购阶段...")
                break

    def sendMail(self, Result, ok_time):

        class retry_times():
            num = 3
            b_succeed = False

        tries = retry_times()

        message = MIMEMultipart('mixed')
        message['Subject'] = '秒杀通知'
        message['From'] = self.Email.sender
        message['To'] = self.Email.receivers

        if Result:
            text = '{} 秒杀成功,请尽快付款~'.format(ok_time)
        else:
            text = '{} 秒杀失败,省钱啦~'.format(ok_time)

        text_plain = MIMEText(text, 'plain', 'utf-8')
        message.attach(text_plain)

        @retry(tries=3, delay=30, backoff=2)
        def sendMailKernel():
            tries.num -= 1
            try:
                tries.b_succeed = True
                smtpObj = smtplib.SMTP()
                smtpObj.connect(self.Email.mail_host, self.Email.port)
                smtpObj.ehlo()
                smtpObj.starttls()
                smtpObj.login(self.Email.mail_user, self.Email.mail_pass)
                smtpObj.sendmail(
                    self.Email.sender, self.Email.receivers, message.as_string())
                smtpObj.quit()
                logger.info('send mail succeed.')
            except smtplib.SMTPException as e:
                tries.b_succeed = False
                logger.info('send mail failed')

                if tries.num > 0:
                    logger.info('SendEmail retry')
                    raise NotImplementedError('Email')

        sendMailKernel()
        return tries.b_succeed

if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('--buy_time', type=str, help='buy time like \'2019-11-11 00:00:00\'')
    parser.add_argument('--login_retry', type=int, help='max retry login times.(default: 3)', default=3)
    parser.add_argument('--email_reminder', type=bool, help='use email to notice result.(default: False)', default=False)

    parser.add_argument('--port', type=int, help='set email port.(default: 25)', default=25)
    parser.add_argument('--mail_host', type=str, help='email host.(default: 163--\'smtp.163.com\')', default='smtp.163.com')
    parser.add_argument('--mail_count', type=str, help='email count.')
    parser.add_argument('--mail_pass', type=str, help='email password.')
    parser.add_argument('--mail_receivers', type=str, help='receive email count.(default: sender)')

    args = parser.parse_args()

    if not args.buy_time:
        logger.info("buy_time must specify.")
        sys.exit(-1)

    buy_time = args.buy_time
    max_retry = args.login_retry

    buyer = BUY_MASHINE(buy_time, max_retry)
    buyer.init()
    buyer.login()
    buyer.working()



参考链接:https://www.jianshu.com/p/5fe9bd8f7674

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/134376.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 升级openssl1.1.1(mix2s哪个版本不断流)

    发现很多OpenSSL的安全漏洞,并且是高危漏洞,所以准备升级CentOS6上的OpenSSL安装,解决安全漏洞;上OpenSSL的官网https://www.openssl.org/,查看一下最新的版本确认一下CentOS默认安装的OpenSSL的版本CentOS6使用的是1.0.1的版本,需要升级到最新的1.0.2s版本CentOS7使用的是1.0.2k版本,可以选…

  • 大数运算模板

    大数运算模板#include#include#include#includeusingnamespacestd;#defineMAX_DIGIT500//大数运算:加法intAdd(int*a,int*b,int*&result){if(a==NULL||b==NULL||re

  • 写一段代码在遍历 ArrayList 时移除一个元素?

    写一段代码在遍历 ArrayList 时移除一个元素?今天楼主继续分享一道经典Java面试题并进行相关知识点的拓展: 上题:写一段代码在遍历ArrayList时移除一个元素?该问题的关键在于面试者使用的是ArrayList的remove()还是Iterator的remove()方法。是使用正确的方式来实现在遍历的过程中移除元素,而不会出现ConcurrentModificationException异常的示例代码。…

  • SQL学习笔记(基础部分)

    SQL学习笔记(基础部分)SQL学习笔记基础部分SQL语法数据库语言对大小写不敏感,用分号分隔每条数据库语言SQL通用数据类型SQL开发,在创建SQL表时要确定每个列要存储的数据类型,每一列都需要一个列名和确定的数据类型常见数据类型自行查询一些重要的SQL命令selectupdatedeleteinsertintocreatedatabasealterdatab

  • java实现excel导入导出功能_java导出excel合并列

    java实现excel导入导出功能_java导出excel合并列一、在后台实现,利用java的poi1、导入jar包,需要导入lib文件夹下如下包:poi-3.11-20141221.jarpoi-ooxml.jarpoi-ooxml-schemas.jar2、在util下写一个公共类,该类主要利用JakartaPOIHSSFAPI组件(用于操作Excel的组件),主要部分包括Excel对象,样式和格式,还有辅助操作。常用组件:……………

  • 局部静态变量的定义_C语言强制转换数据类型

    局部静态变量的定义_C语言强制转换数据类型C语言中定义的静态变量存放在栈区,动态分配的内存空间位于堆区。这题答案为F为大家科普一下知识C语言中局部变量存在栈里,全局变量存静态存储区。局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,每次调用这个局部变量在栈上的位置都不一定相同。局部变量也可以在堆上动态分配,但是记得使用完这个堆空间后要释放之。全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。在程序执行过程中它们占据固定的存储单元,而不动态地进行分配和释放;…

    2022年10月30日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号