欢迎访问的小伙伴! 希望在这里能帮到你。有问题请多多指教~ 点击联系站长

如何用python实现京东多线程多账号抢单?

Python 焦康阳 2评论

你好,我是小焦。今天给大家分享的是如何用python来实现京东平台的自动抢单,多线程多账号来增大我们的抢购成功率。我们都知道京东自营经常会出现一些折扣力度大的商品。而我们每次抢的时候老是一秒钟缺货了,为什么呢?很简单,本来货就少,全部被黄牛拿走了。

    黄牛能用软件搞,我们做为业余的IT人员也是可以凭本事搞的哈哈。至于其中有什么商机,大家下去自己琢磨呗,就像最近的某台酒,某显卡了,那价格翻的了好几倍。好了下面回归正题。

思路

写代码之前肯定要想好如何实现?整体的思路规划肯定少不了。我们要做到多线程多账号同时抢单,第一肯定要实现多账号的储备了,账号这里下去自己申请哦。其次我们要借用上次讲过的cookie池了,我们总不可能开始抢单了才一个一个的账号去登录,黄花菜都凉了。然后就是用cookies登录网页进行模拟抢单下单操作了。将各个模块实现之后,然后应用python的多线程操作就行,或者用多进程都可以的,调用很简单。

准备工作:

  • 自行准备京东账号(京东账号貌似要绑定手机号的,当然是越多越好)
  • 安装谷歌浏览器
  • 安装Chromdriver(整个根据下载的浏览器版本下载,自行百度)
  • 安装redis数据库
  • python以及selenium、redis库

一、建立cookie池

第一步就是建立京东的cookie池,方法参照我的上一篇文章cookie池的建立,或者到文章末尾直接去github看我写的代码。由于京东验证这块非常多,验证码,短信验证等待都是非常麻烦,所以我们还是用selnium来获取cookies的。由于短信验证是随机出来的,所以我们要将网页最大等待时间设置的时间长一点。其次就是根据自己家的设备和网速自行设置。

    最让人无语的就是京东的cookies有效时间只有一天,所以我们时间超过一天必须要重新生成。下面来看看京东的cookie生成操作吧。

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import selenium.common.exceptions as ex
import time
​
class Cookies():
    def __init__(self,username,password):
        # 这里我们使用谷歌浏览器
        self.url = 'https://www.jd.com/'
        self.brower = webdriver.Chrome()
        # 设置最长显示等待时间10s
        self.wait = WebDriverWait(self.brower,30)
        self.username = username
        self.password = password
​
    # 这里进行模拟登录操作
    def openjd(self):
        self.brower.get(self.url)
        #  打开京东主页,打击登录按钮
        self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'link-login'))).click()
        # 选择账号密码登录
        self.wait.until(EC.presence_of_element_located((By.XPATH,'//div[@class="login-tab login-tab-r"]/a'))).click()
        # 输入账号
        self.wait.until(EC.presence_of_element_located((By.ID,'loginname'))).send_keys(self.username)
        # 输入密码
        self.wait.until(EC.presence_of_element_located((By.ID,'nloginpwd'))).send_keys(self.password)
        # 点击登录按钮
        self.wait.until(EC.presence_of_element_located((By.ID,'loginsubmit'))).click()
​
    # 判断账号密码受否错误
    def password_error(self):
        try:
            # 判断是否会出现错误提示,如果出现则出现密码错误提示
            print('正在测试账号密码')
            return bool(self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'msg-error'))))
​
        except ex.TimeoutException:
            return False
​
    # 获取cookies
    def getcookies(self):
        return self.brower.get_cookies()
​
    #  判断账号受否登录成功
    def login_success(self):
        try:
            # 判断页面中是否有退出
            return bool(self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'nickname'))))
​
        except ex.TimeoutException:
            return False
​
​
    def main(self):
        self.openjd()
        # 上面完成打开浏览器填写账号密码操作,验证码这块自己手动操作
        time.sleep(5)
        if self.password_error():
            print('用户名或密码错误')
            self.brower.close()
            return {
                'status':2,
                'content':'用户名或者密码错误'
            }
​
        elif self.login_success():
            print('登录成功')
            # 获取cookies
            cookies = self.getcookies()
​
            self.brower.close()
            print(cookies)
            return {
                'status':1,
                'content':cookies
            }
​
        else:
            print('登录失败')
            self.brower.close()
            return {
                'status':3,
                'content':'登录异常'
            }

生成cookie后记得去测试,这块我们就不展开说了,和上次的方法一样。

二、模拟下单

经过第一波的操作,我们将账号的cookie池生成并测试有效保存到了本地redis数据库中了。下面就是登录,选择商品,加入购物车,结算支付了。切记进行下面操作时,先重新生成cookie池,京东的有效期只有一天。这里我主要做了用cookie登录,然后进入到商品详情页,自动选择我们要买的商品属性,进行一系列点击操作,基本上都是CLASS和LINK_TEXT的筛选。每个步骤我都进行了备注。由于我的网速和硬件限制加载网页慢,所以wait等待时间设置的比较长,这块根据自身情况设置。

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from save import RedisClient
from datetime import datetime
from selenium.webdriver.common.by import By
import selenium.common.exceptions as ex
import json
import time
​
# 普通商品购买流程,这里由于有的商品有多个属性,所以我们yanse使用字典
class putong():
    def __init__(self,url,yanse):
        self.url = url
        # yanse为为我们下单上面的颜色类目选项
        self.yanse = yanse
        self.brower = webdriver.Chrome()
        self.wait = WebDriverWait(self.brower,30)
        self.cookies_db = RedisClient('jdcookies')
​
    #先进行登录
    def login(self):
        print(datetime.now().strftime('%Y-%m-%d  %H:%M:%S '),'开始使用cookies登录账号')
        #随机获取一个账号的cookies
        if self.cookies_db.count() != 0:
            username,cookie = self.cookies_db.random_getall()
            cookies = json.loads(cookie)
            print(datetime.now().strftime('%Y-%m-%d  %H:%M:%S '),'成功获取到账号%s的cookies'%username)
        else:
            print('没有可用的cookies,请重新获取后再进行登录')
            return False
​
        self.brower.get('https://www.jd.com/')
        for cookie in cookies:
            self.brower.add_cookie(cookie)
​
        self.brower.get(self.url)
​
        try:
            # 判断账号是否登录成功
            return bool(self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'nickname'))))
​
        except ex.TimeoutException:
            return False
​
    # 选择商品加入购物车
    def choice(self):
        try:
            # 遍历yanse中设定的值,也就是我们要选择的商品属性,有的商品有多个属性同时选择,所以我们要添加多个
            for i in self.yanse:
                print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'),"正在选择属性",i)
                self.wait.until(EC.presence_of_element_located((By.LINK_TEXT,i)))
​
            #选择属性后点击加入购物车
            self.wait.until(EC.presence_of_element_located((By.XPATH,'//div[@id="choose-btns"]/a[@id="InitCartUrl"]'))).click()
            # 商品加入成功后京东会自动跳入到成功页面,我们检测整个CSS就行
            if self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'success-lcol'))):
                print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'),'商品已成功加入购物车')
                return True
            else:
                print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'),'商品加入购物车失败')
                return False
        except ex.TimeoutException:
            return False
​
    # 购物车页面进行结算
    def pay(self):
        try:
            # 打开购物车页面
            self.brower.get('https://cart.jd.com/cart_index/')
            # 点击全选。这块跳转到结算界面京东自动打勾了,这里我们不用自己操作
            # self.wait.until(EC.presence_of_element_located((By.NAME,'select-all'))).click()
            time.sleep(2)
            # 点击结算
            self.wait.until(EC.presence_of_element_located((By.LINK_TEXT, '去结算'))).click()
            time.sleep(2)
​
            self.wait.until(EC.presence_of_element_located((By.ID, 'order-submit'))).click()
            print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "已提交订单")
            return True
        except ex.TimeoutException:
            print('页面超时')
            return False
​
    #进行登录下单流程
    def run(self):
        if self.login():
            print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "登录成功")
            # 登录成功后选择商品属性
            if self.choice():
                print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "商品属性选择完毕并成功加入购物车")
                if self.pay():
                    print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "成功提交订单,请及时支付")
                    self.brower.close()
                else:
                    print('订单提交失败')
                    self.brower.close()
            else:
                print('商品选择失败')
                self.brower.close()

三、多线程下单

经过上面两步,我们已经从京东下单并跳转到支付页面了。输入密码那些抢单成功后自行操作吧。最后我们调用多线程,多账号同时下单。thread_number是我们设置的最大线程数,自己根据情况而定。下面是截图的局部代码片段,具体的去我的github上面下载。最近github上不去,要源码的私聊我

#下单
    def xiadan(self):
        a = putong(shangping_url,shuxing)
        a.run()
        
# 下单模块,
    def run(self):
        thread_list = []
        # p = Pool(4)
        # 根据我们设置的数量添加线程
        for i in range(0,thread_number):
            print('启动线程',i)
            # 这块遇到大坑,多线程调用函数只写函数名,千万不要加括号,切记!切记!切记!坑的要死
            a = threading.Thread(target=self.xiadan,args=(),)
            print('加入线程',i)
            thread_list.append(a)
            # thread_list.append(Process(target=putong(url=shangping_url, yanse=shuxing).run(),name=str(i),))
​
​
        # 启动线程
        for m in thread_list:
            m.start()
​
        for thread in thread_list:
            thread.join()

今天的内容我们就分享到这,整体也是非常简单,内容不多,太多的东西可能花到中途的调试过程中了。整体运行是没有问题,大伙根据自己情况修改。下次我会添加UI界面,并打包成可配置的exe文件给大伙分享出来。

github地址:https://github.com/zhanjiuyou

喜欢 (28)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(2)个小伙伴在吐槽
  1. 博主赶紧出exe版本,感谢
    十里春风2021-03-19 13:14 回复
    • 下一篇文章已经出了,最近会改动下
      焦康阳2021-04-13 20:31 回复