python使用requests秒杀茅台(适用某宝,也可抢购其他商品)

前言

关于茅台抢购,看过不下一百篇小文章,浏览来浏览去,也找不到几篇合适的。虽然有很多人发布了使用selenium抢购茅台的脚本,但个人觉得这些没有直接使用requests提交订单来的快。于是!就有了你现在读的文章!废话不多说,开搞!

准备工作

安装python,这就不用我说吧?至于开发工具使用什么看自己心情,我这里使用的是vscode,不知道如何操作的可以参考这位博主的http://t.csdn.cn/Xh3LG。这位博主的文章下面还有selenium的安装教程,可以顺便看一下,因为我这里也要用到selenium登录,我就不重复造轮子了。

分析一波抢购流程

1、登录

2、requests请求“确认订单”所需信息

3、requests请求“提交订单”

看似简单的三步,我可花费了好多心血来研究啊,得掉多少头发!

具体实现过程

import re, time, random, datetime, sys, requests, threading, psutil
from requests.cookies import RequestsCookieJar
from selenium.webdriver.common.by import By
from multiprocessing import Queue
from urllib.parse import quote
from selenium import webdriver
from io import BytesIO
from PIL import Image




class Login():
    def __init__(self):
        #设置关键词进行匹配或判断,下同
        self.key_word1 = '账号管理'
        self.key_word2 = '安全链接'
        self.j = 0
        #创建队列存放post订单结果
        self.queue = Queue(maxsize=100)
        # 创建Session对象  requests库的session对象会在同一个session实例的所有请求之间使用cookies保持登录状态
        self.session = requests.session()
        #设置headers
        ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.50"
        self.headers = {
            'User-Agent': ua
        }
        self.session.headers.update(self.headers)


    # 扫码登录,获取cookies
    def get_cookies(self):
        options = webdriver.ChromeOptions()
        options.add_experimental_option('excludeSwitches', ['enable-logging'])
        options.add_argument('--headless')
        browser = webdriver.Chrome(options=options)
        url = 'https://login.taobao.com/member/login.jhtml'
        browser.get(url)
        # 点击跳转扫码界面
        browser.find_element(By.XPATH,'/html/body/div[1]/div[2]/div[3]/div/div/div/div[1]/i').click()
        time.sleep(round(random.uniform(1,2),2))
        # 获取并保存二维码截图
        qrcode_img_data=browser.find_element(By.XPATH, '//*[@id="login"]/div[2]/div/div[1]/div[1]').screenshot_as_png
        qrcode_img = Image.open(BytesIO(qrcode_img_data))
        qrcode_img.save('qrcode.png')
        qrcode_img.show()
        print("请扫码登录!")
        time.sleep(2)
        # 每隔1.5秒判断一次是否登录成功
        t=0
        while t < 40:
            try:
                info = browser.find_element(By.XPATH, '//*[@id="J_Col_Main"]/div/div[1]/div/div[1]/div[1]/div/div[1]/a/em').text
                print('您的帐户:' + info)
                for proc in psutil.process_iter():  # 遍历当前process
                    if proc.name() == "Microsoft.Photos.exe":
                        proc.kill()  # 关闭该process
                break
            except:
                time.sleep(1.5)
                t+=1
        # 获取Cookie并保持在session中
        cookies = browser.get_cookies()
        time.sleep(round(random.uniform(1,2),2))
        browser.quit()
        selenium_cookies = cookies
        tmp_cookies = RequestsCookieJar()
        for item in selenium_cookies:
            tmp_cookies.set(item["name"], item["value"])
        self.session.cookies.update(tmp_cookies)


    #登录
    def login(self):
        print("登录中...")
        try:
            req=self.session.get('https://i.taobao.com/user/baseInfoSet.htm?').text
            if self.key_word1 in req:
                print("自动登录成功!")
            else:
                print("自动登录失败!\n请再次扫码登录!")
                self.get_cookies()
                self.session.get('https://i.taobao.com/user/baseInfoSet.htm?').text
                if self.key_word1 in req:
                    print("自动登录成功!")
                else:
                    print("自动登录失败!\n请手动完成该任务")
                    sys.exit(0)
        except:
            print('程序出错!')
            sys.exit(0)


    # 提交订单
    def submitOrder(self, url, skuId, setTime, quantity):
        self.url = url
        quantity = '_' + quantity + '_'
        # 获取cookies并登录
        self.cookies=self.get_cookies()
        self.login()
        time.sleep(round(random.uniform(1,2),2))
        # 进入商品详情页 
        self.req = self.session.get(url=self.url).text
        time.sleep(round(random.uniform(1,2),2))
        # 提取 key datas
        self.patterGoods()
        time.sleep(round(random.uniform(1,2),2))

        # 确认订单
        data = {
            "buy_param": self.auction[0] + quantity + skuId
        }
        url = 'https://buy.tmall.com/order/confirm_order.htm?x-itemid=' + self.auction[0] + '&x-uid=' + self.userId[0]
        k = 0
        while True:
            print("\r购买倒计时:%.3f"%(setTime-time.time()),end="",flush=True)
            if (time.time() >= setTime):
                print('\n')
                print(datetime.datetime.now())
                while True:
                    self.req = self.session.post(url=url, data=data).text
                    # 获取数据
                    key = self.patterData()
                    k+=1
                    if(k==50):
                        print("\n确认订单失败!下次加油哦")
                        print(datetime.datetime.now())
                        sys.exit(0)
                    if(key):
                        print("\n确认订单成功!")
                        print(datetime.datetime.now())
                        break
                break

        # 提交订单
        data = {
            "endpoint": self.endpoint,
            "linkage": self.linkage,
            "data": self.data,
            "action": self.action,
            "_tb_token_": self.tbToken,
            "event_submit_do_confirm": self.event,
            "praper_alipay_cashier_domain": self.unitSuffix,
            "input_charset": self.charset,
            "hierarchy": self.hierarchy
        }
        url = 'https://buy.tmall.com/auction/confirm_order.htm?x-itemid=' + self.auction[0] + '&x-uid=' + self.userId[0] + '&submitref=' + self.submitUrl
        #多线程,提高抢购效率
        thread_list=[]
        for i in range(1,80):
            t = threading.Thread(target=self.post, args=(url, data))
            thread_list.append(t)
        l = len(thread_list)
        # 启动线程
        for i in range(0,l-1):
            thread_list[i].start()
        # 关闭线程
        for t in range(0,l-1):
            thread_list[i].join()
        while self.queue.empty() == False:
            req = self.queue.get()
            if self.key_word2 in req:
                print('提交订单成功!请快尽快付款!')
                self.j = 1
                break
        if self.j == 0:
            print('提交订单失败!请下次重试!')
        print('Buy End!')
        sys.exit(0)


    # 提取信息:商品详情
    def patterGoods(self):
        # 页面id
        self.auction=re.findall(r'(?<=auction=).*?(?=&)', self.req)
        # 用户id
        self.userId=re.findall(r'(?<=&userid=).*?(?=&)', self.req)
        # 购买端token
        tbTokens=re.findall(r'(?<=yunid=&).*?(?=&)', self.req)
        self.tbToken = tbTokens[0]


    # 提取信息:生成订单数据
    def patterData(self):
        # 正则匹配
        data=re.findall(r'(?<="secretValue":).*?(?=,"unitSuffix")', self.req)
        if not data:
            return False    
        self.submitUrl = ''.join(data)
        self.submitUrl=re.sub(r'"', '', self.submitUrl)
        self.submitUrl=re.sub(r',', '&', self.submitUrl)
        self.submitUrl=re.sub(r':', '=', self.submitUrl)

        data = re.findall(r'(?<="endpoint":).*?(?=,"data")', self.req)
        self.endpoint = ''.join(data)
        self.endpoint = quote(self.endpoint)

        data = re.findall(r'(?<="action":").*?(?=","event_submit_do_confirm")', self.req)
        self.action = ''.join(data)
        data = re.findall(r'(?<="event_submit_do_confirm":").*?(?=","input_charset")', self.req)
        self.event = ''.join(data)
        data = re.findall(r'(?<="input_charset":").*?(?=","pcSubmitUrl")', self.req)
        self.charset = ''.join(data)
        data = re.findall(r'(?<="unitSuffix":").*?(?="}},)', self.req)
        unitSuffix = ''.join(data)
        self.unitSuffix = "cashier" + unitSuffix

        data=re.findall(r'(?<="data":).*?(?=,"linkage")', self.req)
        self.data = ''.join(data)
        self.data = quote(self.data)     # url 编码

        data=re.findall(r'(?<="linkage":).*?(?=,"hierarchy")', self.req)
        self.linkage = ''.join(data)
        self.linkage = quote(self.linkage)

        data=re.findall(r'(?<="hierarchy":).*?(?=,"container")', self.req)
        self.hierarchy = ''.join(data)
        self.hierarchy = quote(self.hierarchy)
        return True


    def post(self, url, data):
        req = self.session.post(url=url, data=data).text
        self.queue.put(req)

也就……也就一两百行代码吧,当然这些代码也不是完完全全由我敲出来的,我只是站在巨人的肩膀上(doge)

这不是全部的代码,还有还有……

from TTime import postTime
import TbMoudle, time




if __name__ == "__main__":
    # 商品链接
    #url = 'https://detail.tmall.com/item.htm?id=576148466933&spm=a1z09.2.0.0.28032e8dcv63yd&_u=1340hb4c2d7d&skuId=4516861399500'            #用来测试的淘宝链接,通过
    url = 'https://chaoshi.detail.tmall.com/item.htm?id=20739895092&spm=a1z0k.7628870.0.0.6d8537de1tkYdk&_u=t2dmg8j26111&skuId=4227830352490'           #茅台链接
    #url = 'https://chaoshi.detail.tmall.com/item.htm?spm=a1z0d.6639537/tb.1997196601.3.52367484NWZmwA&id=541462757234&skuId=5029227863773'            #用来测试的天猫链接,通过
    '''
    #设定抢购物品的url
    #详情页网址是用电脑登录,选好数量和样式之后的网址
    url=str(input("请输入详情页网址:\n"))
    '''


    # 仅适用于 skUid 在链接末  即已选好商品规格的链接
    skuIds = url.split('=')
    k = len(skuIds)-1
    skuId = skuIds[k]
    quantity = '1'          # 购买数量


    # 定时 + 毫秒延迟校正
    action_time='20:00:00'
    post_date = time.strftime("%Y/%#m/%#d",time.localtime(time.time()))
    post_time = post_date + ' ' + action_time
    setTime = postTime(post_time) - 0.2


    # 实例化对象 
    a = TbMoudle.Login()
    a.submitOrder(url, skuId, setTime, quantity)

还有一段,是上面这段代码所需的模块之一!

import time




# 输入触发时间 返回时间戳
def postTime(setTime):
    #转换成时间数组
    timeArray = time.strptime(setTime, "%Y/%m/%d %H:%M:%S")
    #转换成时间戳
    timestamp = time.mktime(timeArray)
    return timestamp

ok,全部代码都在上面了,有时间会打包放在github上面,后面再更!别催!还有不要忘记安装第二段代码所需依赖!依赖放在下面了!一个一个装吧,哈哈!

Pillow==9.3.0
psutil==5.9.1
requests==2.28.1
selenium==4.5.0

说明

第一段代码copy下来命名为TbMoudle.py,第二段命名为main.py(随便命名也行),第三段命名为TTime.py,然后运行第二段代码即可。想要抢购茅台,在19:55左右运行main.py,过几秒会出现二维码,60秒内使用淘宝扫码即可(不要问我为什么不用保存的cookies登录,问就是不方便)。虽然到现在我还没有抢到过,但一定不是我的代码的问题吧?对吧???嗯???

参考

想法来源:

http://t.csdn.cn/yNAZk

requests使用介绍:

Python Requests库使用指南 – 掘金

selenium使用说明:

http://t.csdn.cn/DQd5n

……忘记还参考过谁了……如有相同,联系博主进行修改!

代码是不可能自己敲的(doge),这里借鉴了很多别人的代码,不过这些思路是我自己想的,会秃头的,觉得有用的能不能……点赞啥的???嗯???行不行???python使用requests秒杀茅台(适用某宝,也可抢购其他商品)

说明:本文仅供学习研究,严禁从事非法活动,下载后请勿用于商业用途,任何后果由使用者本人负责;本文中使用的部分图片以及部分代码来自于网络,如有侵权,请联系博主进行删除

转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

作者:希声

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年3月5日 下午4:58
下一篇 2023年3月5日 下午4:59

相关推荐