欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

教你用Python寫一個(gè)京東自動(dòng)下單搶購(gòu)腳本

 更新時(shí)間:2023年03月23日 15:46:58   作者:程序猿周周  
很多朋友都有網(wǎng)購(gòu)搶購(gòu)限量商品的經(jīng)歷,有時(shí)候蹲點(diǎn)搶怎么也搶不到,今天小編帶你們學(xué)習(xí)怎么用Python寫一個(gè)京東自動(dòng)下單搶購(gòu)腳本,以后再也不用拼手速拼網(wǎng)速啦,快來(lái)一起看看吧

1 問(wèn)題背景

經(jīng)過(guò)無(wú)數(shù)次搶購(gòu)失敗后,發(fā)現(xiàn)商家會(huì)不定時(shí)的放出少量貨源,目測(cè)每次會(huì)有幾臺(tái)。如果我們編寫一個(gè)腳本程序24小時(shí)不間斷監(jiān)聽商品庫(kù)存,一旦查詢到貨源便開始嘗試自動(dòng)下單,這樣就可以極大提高我們的成功概率。

2 設(shè)計(jì)思路

京東對(duì)于商品的搶購(gòu)主要分為兩種:

預(yù)約搶購(gòu):到點(diǎn)開放購(gòu)買,和普通商品下單流程一致;秒殺商品:?jiǎn)为?dú)的搶購(gòu)接口和下單流程。

當(dāng)然本次針對(duì)的預(yù)約搶購(gòu)類或無(wú)貨訂購(gòu)類,即整體下單流程和購(gòu)買普通商品時(shí)一樣:

登錄賬號(hào) → 進(jìn)入購(gòu)物車 → 選擇搶購(gòu)商品 → 點(diǎn)擊去結(jié)算 → 點(diǎn)擊提交訂單 → 選擇付款方式并付款。

3 具體實(shí)現(xiàn)

由于筆者本人沒(méi)有一個(gè)可以抓包的客戶端,決定采用京東 WEB 端接口實(shí)現(xiàn)我們的腳本程序。

于是經(jīng)過(guò)對(duì)京東網(wǎng)頁(yè)下單流程的分析,將我們的腳本程序分為四個(gè)模塊:賬號(hào)登錄模塊、庫(kù)存監(jiān)聽模塊、購(gòu)物車管理模塊、訂單管理模塊。

3.1 賬號(hào)登錄

由于使用賬號(hào)密碼時(shí)有驗(yàn)證碼限制,此處采用掃碼登錄方式繞過(guò)。

如對(duì)掃碼登錄不熟悉或感興趣的同學(xué)可以查看周周之前的博文 掃碼登錄原理和實(shí)現(xiàn)

本次只要針對(duì)京東登錄頁(yè)進(jìn)行抓包分析,找到幾個(gè)有用接口:

獲取登錄二維碼

def getQRcode(self):
    url = 'https://qr.m.jd.com/show'
    payload = {
        'appid': 133,
        'size': 147,
        't': str(int(time.time() * 1000)),
    }
    headers = {
        'User-Agent': self.userAgent,
        'Referer': 'https://passport.jd.com/new/login.aspx',
    }
    resp = self.sess.get(url=url, headers=headers, params=payload)

    if not self.respStatus(resp):
        return None

    return resp.content

獲取Ticket

def getQRcodeTicket(self):
    url = 'https://qr.m.jd.com/check'
    payload = {
        'appid': '133',
        'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
        'token': self.sess.cookies.get('wlfstk_smdl'),
        '_': str(int(time.time() * 1000)),
    }
    headers = {
        'User-Agent': self.userAgent,
        'Referer': 'https://passport.jd.com/new/login.aspx',
    }
    resp = self.sess.get(url=url, headers=headers, params=payload)

    if not self.respStatus(resp):
        return False

    respJson = self.parseJson(resp.text)
    if respJson['code'] != 200:
        return None
    else:
        return respJson['ticket']

驗(yàn)證 Ticket

def getQRcodeTicket(self):
    url = 'https://qr.m.jd.com/check'
    payload = {
        'appid': '133',
        'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
        'token': self.sess.cookies.get('wlfstk_smdl'),
        '_': str(int(time.time() * 1000)),
    }
    headers = {
        'User-Agent': self.userAgent,
        'Referer': 'https://passport.jd.com/new/login.aspx',
    }
    resp = self.sess.get(url=url, headers=headers, params=payload)

    if not self.respStatus(resp):
        return False

    respJson = self.parseJson(resp.text)
    if respJson['code'] != 200:
        return None
    else:
        return respJson['ticket']

此時(shí)驗(yàn)證 Ticket 有效后使用 pickle 庫(kù)將程序會(huì)話中的 cookie 保存到本地以便下次使用。

3.2 庫(kù)存監(jiān)聽

庫(kù)存監(jiān)聽較為簡(jiǎn)單,分析商品詳情頁(yè),獲取店鋪ID以及商品分類屬性:

獲取商品詳情信息

def getItemDetail(self, skuId):
    url = 'https://item.jd.com/{}.html'.format(skuId)
    page = requests.get(url=url, headers=self.headers)

    html = etree.HTML(page.text)
    vender = html.xpath(
        '//div[@class="follow J-follow-shop"]/@data-vid')[0]
    cat = html.xpath('//a[@clstag="shangpin|keycount|product|mbNav-3"]/@href')[
        0].replace('//list.jd.com/list.html?cat=', '')

    if not vender or not cat:
        raise Exception('獲取商品信息失敗,請(qǐng)檢查SKU是否正確')

    detail = dict(catId=cat, venderId=vender)
    return detail

查詢庫(kù)存

def getItemStock(self, skuId, num, areaId):

    item = self.itemDetails.get(skuId)

    if not item:
        return False

    url = 'https://c0.3.cn/stock'
    payload = {
        'skuId': skuId,
        'buyNum': num,
        'area': areaId,
        'ch': 1,
        '_': str(int(time.time() * 1000)),
        'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
        # get error stock state without this param
        'extraParam': '{"originid":"1"}',
        # get 403 Forbidden without this param (obtained from the detail page)
        'cat': item.get('catId'),
        # return seller information with this param (can't be ignored)
        'venderId': item.get('venderId')
    }
    headers = {
        'User-Agent': self.userAgent,
        'Referer': 'https://item.jd.com/{}.html'.format(skuId),
    }

    respText = ''
    try:
        respText = requests.get(
            url=url, params=payload, headers=headers, timeout=self.timeout).text
        respJson = self.parseJson(respText)
        stockInfo = respJson.get('stock')
        skuState = stockInfo.get('skuState')  # 商品是否上架
        # 商品庫(kù)存狀態(tài):33 -- 現(xiàn)貨  0,34 -- 無(wú)貨  36 -- 采購(gòu)中  40 -- 可配貨
        stockState = stockInfo.get('StockState')
        return skuState == 1 and stockState in (33, 40)

3.3 購(gòu)物車操作

無(wú)貨商品加入到購(gòu)物車我們是無(wú)法通過(guò)頁(yè)面操作的,我們這邊可以使用其他有貨商品進(jìn)行嘗試,主要查看購(gòu)物車的增刪改查接口:

取消所有選中商品

def uncheckCartAll(self):
    """ 取消所有選中商品
    return 購(gòu)物車信息
    """
    url = 'https://api.m.jd.com/api'

    headers = {
        'User-Agent': self.userAgent,
        'Content-Type': 'application/x-www-form-urlencoded',
        'origin': 'https://cart.jd.com',
        'referer': 'https://cart.jd.com'
    }

    data = {
        'functionId': 'pcCart_jc_cartUnCheckAll',
        'appid': 'JDC_mall_cart',
        'body': '{"serInfo":{"area":"","user-key":""}}',
        'loginType': 3
    }

    resp = self.sess.post(url=url, headers=headers, data=data)

    # return self.respStatus(resp) and resp.json()['success']
    return resp

加入購(gòu)入車

def addCartSku(self, skuId, skuNum):
    """ 加入購(gòu)入車
    skuId 商品sku
    skuNum 購(gòu)買數(shù)量
    retrun 是否成功
    """
    url = 'https://api.m.jd.com/api'
    headers = {
        'User-Agent': self.userAgent,
        'Content-Type': 'application/x-www-form-urlencoded',
        'origin': 'https://cart.jd.com',
        'referer': 'https://cart.jd.com'
    }
    data = {
        'functionId': 'pcCart_jc_cartAdd',
        'appid': 'JDC_mall_cart',
        'body': '{\"operations\":[{\"carttype\":1,\"TheSkus\":[{\"Id\":\"' + skuId + '\",\"num\":' + str(skuNum) + '}]}]}',
        'loginType': 3
    }
    resp = self.sess.post(url=url, headers=headers, data=data)
    return self.respStatus(resp) and resp.json()['success']

修改購(gòu)物車商品數(shù)量

def changeCartSkuCount(self, skuId, skuUid, skuNum, areaId):
    """ 修改購(gòu)物車商品數(shù)量
    skuId 商品sku
    skuUid 商品用戶關(guān)系
    skuNum 購(gòu)買數(shù)量
    retrun 是否成功
    """
    url = 'https://api.m.jd.com/api'
    headers = {
        'User-Agent': self.userAgent,
        'Content-Type': 'application/x-www-form-urlencoded',
        'origin': 'https://cart.jd.com',
        'referer': 'https://cart.jd.com'
    }
    body = '{\"operations\":[{\"TheSkus\":[{\"Id\":\"'+skuId+'\",\"num\":'+str(
        skuNum)+',\"skuUuid\":\"'+skuUid+'\",\"useUuid\":false}]}],\"serInfo\":{\"area\":\"'+areaId+'\"}}'
    data = {
        'functionId': 'pcCart_jc_changeSkuNum',
        'appid': 'JDC_mall_cart',
        'body': body,
        'loginType': 3
    }
    resp = self.sess.post(url=url, headers=headers, data=data)
    return self.respStatus(resp) and resp.json()['success']

以上是我們一次購(gòu)買需要用到的最少接口,為了不破壞賬戶購(gòu)物車中已有數(shù)據(jù),采用一下步驟準(zhǔn)備好購(gòu)物車:

取消全部勾選(返回購(gòu)物車信息);已在購(gòu)物車則修改商品數(shù)量;不在購(gòu)物車則加入購(gòu)物車。 3.4 訂單操作

當(dāng)我們準(zhǔn)備好購(gòu)物車之后(選中購(gòu)買商品以及調(diào)整購(gòu)買數(shù)量),就可以進(jìn)行下一步訂單相關(guān)操作:

獲取結(jié)算單

def getCheckoutPage(self):
    """獲取訂單結(jié)算頁(yè)面信息
    :return: 結(jié)算信息 dict
    """
    url = 'http://trade.jd.com/shopping/order/getOrderInfo.action'
    # url = 'https://cart.jd.com/gotoOrder.action'
    payload = {
        'rid': str(int(time.time() * 1000)),
    }
    headers = {
        'User-Agent': self.userAgent,
        'Referer': 'https://cart.jd.com/cart',
    }

提交訂單

def submitOrder(self):
    """提交訂單
    :return: True/False 訂單提交結(jié)果
    """
    url = 'https://trade.jd.com/shopping/order/submitOrder.action'
    # js function of submit order is included in https://trade.jd.com/shopping/misc/js/order.js?r=2018070403091

    data = {
        'overseaPurchaseCookies': '',
        'vendorRemarks': '[]',
        'submitOrderParam.sopNotPutInvoice': 'false',
        'submitOrderParam.trackID': 'TestTrackId',
        'submitOrderParam.ignorePriceChange': '0',
        'submitOrderParam.btSupport': '0',
        'riskControl': self.risk_control,
        'submitOrderParam.isBestCoupon': 1,
        'submitOrderParam.jxj': 1,
        'submitOrderParam.trackId': self.track_id,
        'submitOrderParam.eid': self.eid,
        'submitOrderParam.fp': self.fp,
        'submitOrderParam.needCheck': 1,
    }

4 完整代碼

項(xiàng)目完整源碼請(qǐng)看:https://github.com/zas023/JdBuyer

在這里插入圖片描述

目前完成度較高,可以直接使用:

并提供 Windows 和 macOS 兩種客戶端;支持下單后微信通知觸達(dá)。

5 總結(jié)

腳本自動(dòng)化操作確實(shí)可以實(shí)現(xiàn)搶購(gòu)商品,相比手動(dòng)操作有較高的下單成功率,但僅靠上述代碼想與某些專業(yè)搶購(gòu)的服務(wù)器進(jìn)行比較還是相去甚遠(yuǎn)。

在這里插入圖片描述

到此這篇關(guān)于教你用Python寫一個(gè)京東自動(dòng)下單搶購(gòu)腳本的文章就介紹到這了,更多相關(guān)Python京東自動(dòng)搶購(gòu)腳本內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python簡(jiǎn)單區(qū)塊鏈模擬詳解

    python簡(jiǎn)單區(qū)塊鏈模擬詳解

    這篇文章主要介紹了python簡(jiǎn)單區(qū)塊鏈模擬詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • python爬蟲之百度API調(diào)用方法

    python爬蟲之百度API調(diào)用方法

    下面小編就為大家?guī)?lái)一篇python爬蟲之百度API調(diào)用方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • 教你怎么用Python處理excel實(shí)現(xiàn)自動(dòng)化辦公

    教你怎么用Python處理excel實(shí)現(xiàn)自動(dòng)化辦公

    這篇文章主要介紹了教你怎么用Python處理excel實(shí)現(xiàn)自動(dòng)化辦公,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • educoder之Python數(shù)值計(jì)算庫(kù)Numpy圖像處理詳解

    educoder之Python數(shù)值計(jì)算庫(kù)Numpy圖像處理詳解

    這篇文章主要為大家介紹了educoder之Python數(shù)值計(jì)算庫(kù)Numpy圖像處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • pandas數(shù)據(jù)框,統(tǒng)計(jì)某列數(shù)據(jù)對(duì)應(yīng)的個(gè)數(shù)方法

    pandas數(shù)據(jù)框,統(tǒng)計(jì)某列數(shù)據(jù)對(duì)應(yīng)的個(gè)數(shù)方法

    下面小編就為大家分享一篇pandas數(shù)據(jù)框,統(tǒng)計(jì)某列數(shù)據(jù)對(duì)應(yīng)的個(gè)數(shù)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Python?Playwright的使用詳解

    Python?Playwright的使用詳解

    本篇博客為大家介紹一款新的自動(dòng)化測(cè)試工具,效果類似?selenium,但是這個(gè)模塊年輕。模塊名稱為?playwright-python,微軟開源的,是針對(duì)?Python?語(yǔ)言的純自動(dòng)化工具,感興趣的可以了解一下
    2022-10-10
  • python如何將自己的包上傳到PyPi并可通過(guò)pip安裝的方法步驟

    python如何將自己的包上傳到PyPi并可通過(guò)pip安裝的方法步驟

    本文主要介紹了python如何將自己的包上傳到PyPi并可通過(guò)pip安裝的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • python?中?lxml?的?etree?標(biāo)簽解析

    python?中?lxml?的?etree?標(biāo)簽解析

    這篇文章主要介紹了python?中l(wèi)xml的etree?標(biāo)簽解析,文章圍繞主題展開詳細(xì)內(nèi)容,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)或工作有所幫助
    2022-04-04
  • Python編程pytorch深度卷積神經(jīng)網(wǎng)絡(luò)AlexNet詳解

    Python編程pytorch深度卷積神經(jīng)網(wǎng)絡(luò)AlexNet詳解

    AlexNet和LeNet的架構(gòu)非常相似。這里我們提供了一個(gè)稍微精簡(jiǎn)版本的AlexNet,去除了當(dāng)年需要兩個(gè)小型GPU同時(shí)運(yùn)算的設(shè)計(jì)特點(diǎn)
    2021-10-10
  • Python爬取阿拉丁統(tǒng)計(jì)信息過(guò)程圖解

    Python爬取阿拉丁統(tǒng)計(jì)信息過(guò)程圖解

    這篇文章主要介紹了Python爬取阿拉丁統(tǒng)計(jì)信息過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05

最新評(píng)論