溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用Python在京東上搶口罩

發(fā)布時(shí)間:2021-06-08 13:40:29 來(lái)源:億速云 閱讀:161 作者:小新 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)如何使用Python在京東上搶口罩,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

使用模塊

首先打開項(xiàng)目中 requirements.txt 文件,看下它都需要哪些模塊:

  • requests:類似 urllib ,主要用于向網(wǎng)站發(fā)送 HTTP 請(qǐng)求。

  • beautifulsoup4: HTML 解析器,用于將 HTML 文檔轉(zhuǎn)換成一個(gè)復(fù)雜的樹形結(jié)構(gòu)。

  • pillow:Python 圖像處理標(biāo)準(zhǔn)庫(kù),用于識(shí)別驗(yàn)證碼。

配置文件

一般項(xiàng)目中我們都需要把一些可配置的內(nèi)容放到配置文件中,現(xiàn)在我們來(lái)看下這里主要配置項(xiàng):

# 郵寄地所屬地區(qū)ID
area = 123456
# 這是配置的商品的ID
skuid = 6828101
# 打碼服務(wù)器的地址
captchaUrl = http://xxx/pic
# 通知郵箱
mail = xxxxxx@qq.com
# cookie的設(shè)置
cookies_String = shshshfpa21jsda8923892949204923123
OK,有了配置文件,那我們就得有一段讀取配置文件的代碼,這段代碼實(shí)現(xiàn)將配置內(nèi)容加載到內(nèi)存中。
import os
import configparser
# 加載配置文件
class Config(object):
 def __init__(self, config_file='configDemo.ini'):
  self._path = os.path.join(os.getcwd(), config_file)
  if not os.path.exists(self._path):
   raise FileNotFoundError("No such file: config.ini")
  self._config = configparser.ConfigParser()
  self._config.read(self._path, encoding='utf-8-sig')
  self._configRaw = configparser.RawConfigParser()
  self._configRaw.read(self._path, encoding='utf-8-sig')
 def get(self, section, name):
  return self._config.get(section, name)
 def getRaw(self, section, name):
  return self._configRaw.get(section, name)

主程序模塊

我看 GitHub 上也有實(shí)現(xiàn)了運(yùn)行程序后通過京東 App 掃碼登陸,然后再通過登陸 Cookie 訪問網(wǎng)站的,不過這里并沒有使用這種方式,畢竟我們打開瀏覽器開發(fā)者工具也能很容易獲取到登陸的 Cookie ,這里就是將 Cookie 直接放到配置文件里的方式。

# 主程序入口
# 檢查是否存在要搶購(gòu)的端口,然后進(jìn)入循環(huán)掃描
if len(skuids) != 1:
 logger.info('請(qǐng)準(zhǔn)備一件商品')
skuId = skuids[0]
flag = 1
# 循環(huán)掃描該商品是否有貨,有庫(kù)存即會(huì)自動(dòng)下單,無(wú)庫(kù)存則休眠后繼續(xù)掃描
while (1):
 try:
  # 初始化校驗(yàn)
  if flag == 1:
   logger.info('當(dāng)前是V3版本')
   validate_cookies() # 校驗(yàn)登陸狀態(tài)
   getUsername()  # 獲取登陸用戶信息
   select_all_cart_item() # 全選購(gòu)物車
   remove_item()   # 刪除購(gòu)物車
   add_item_to_cart(skuId) # 增加搶購(gòu)的商品
  # 檢測(cè)配置文件修改
  if int(time.time()) - configTime >= 60:
   check_Config()
  logger.info('第' + str(flag) + '次 ')
  # 計(jì)數(shù)器
  flag += 1
  # 檢查庫(kù)存模塊
  inStockSkuid = check_stock(checksession, skuids, area)
  # 自動(dòng)下單模塊
  V3AutoBuy(inStockSkuid)
  # 休眠模塊
  timesleep = random.randint(1, 3) / 10
  time.sleep(timesleep)
  # 校驗(yàn)是否還在登錄模塊
  if flag % 100 == 0:
   V3check(skuId)
 except Exception as e:
  print(traceback.format_exc())
  time.sleep(10)

以上就是該項(xiàng)目主程序,我已經(jīng)將代碼在原來(lái)基礎(chǔ)上增加了些注釋,可以讓我們更容易明白代碼的含義。下面我們就選擇幾個(gè)比較關(guān)鍵的代碼分析一下。

登陸狀態(tài)校驗(yàn)

# 校驗(yàn)登陸狀態(tài)
def validate_cookies():
 for flag in range(1, 3):
  try:
   targetURL = 'https://order.jd.com/center/list.action'
   payload = {
    'rid': str(int(time.time() * 1000)),
   }
   resp = session.get(url=targetURL, params=payload, allow_redirects=False)
   if resp.status_code == requests.codes.OK:
    logger.info('登錄成功')
    return True
   else:
    logger.info('第【%s】次請(qǐng)重新獲取cookie', flag)
    time.sleep(5)
    continue
  except Exception as e:
   logger.info('第【%s】次請(qǐng)重新獲取cookie', flag)
   time.sleep(5)
   continue
 message.sendAny('腳本登錄cookie失效了,請(qǐng)重新登錄')
 sys.exit(1)

以上代碼是每次調(diào)用時(shí),循環(huán)兩次獲取通過 session 獲取當(dāng)前登陸狀態(tài),如果兩次后依然失敗則退出程序。

添加商品到購(gòu)物車

接下來(lái)我們?cè)倏聪氯绻砑由唐返劫?gòu)物車的,代碼如下:

def add_item_to_cart(sku_id):
 # 請(qǐng)求添加商品url
 url = 'https://cart.jd.com/gate.action'
 payload = {
  'pid': sku_id,
  'pcount': 1,
  'ptype': 1,
 }
 # 返回結(jié)果
 resp = session.get(url=url, params=payload)
 # 套裝商品加入購(gòu)物車后直接跳轉(zhuǎn)到購(gòu)物車頁(yè)面
 if 'https://cart.jd.com/cart.action' in resp.url:
  result = True
 else:
  # 普通商品成功加入購(gòu)物車后會(huì)跳轉(zhuǎn)到提示 "商品已成功加入購(gòu)物車!" 頁(yè)面
  soup = BeautifulSoup(resp.text, "html.parser")
  result = bool(soup.select('h4.ftx-02')) # [<h4 class="ftx-02">商品已成功加入購(gòu)物車!</h4>]
 if result:
  logger.info('%s 已成功加入購(gòu)物車', sku_id)
 else:
  logger.error('%s 添加到購(gòu)物車失敗', sku_id)

在這里,只是簡(jiǎn)單幾行代碼就能將端口添加到購(gòu)物車了,而且這里還區(qū)分了不同類型商品添加到購(gòu)物車返回的頁(yè)面結(jié)果是不同的,所以要進(jìn)行區(qū)別處理。

購(gòu)買商品

將商品添加到購(gòu)物車了,接下來(lái)我們就得提交結(jié)算頁(yè)了,也就是將商品提交到付款頁(yè)面,這段代碼有點(diǎn)多,我簡(jiǎn)化了下并加了些注釋:

def submit_order(session, risk_control, sku_id, skuids, submit_Time, encryptClientInfo, is_Submit_captcha, payment_pwd,
     submit_captcha_text, submit_captcha_rid):
 # 提交端口的url
 url = 'https://trade.jd.com/shopping/order/submitOrder.action'
 # 提交參數(shù)
 data = {
  'overseaPurchaseCookies': '',
  'vendorRemarks': '[]',
  'submitOrderParam.sopNotPutInvoice': 'false',
  'submitOrderParam.trackID': 'TestTrackId',
  'submitOrderParam.ignorePriceChange': '0',
  'submitOrderParam.btSupport': '0',
  'riskControl': risk_control,
  'submitOrderParam.isBestCoupon': 1,
  'submitOrderParam.jxj': 1,
  'submitOrderParam.trackId': '9643cbd55bbbe103eef18a213e069eb0', # Todo: need to get trackId
  'submitOrderParam.needCheck': 1,
 }
 # 如果用到京豆會(huì)需要輸入支付密碼
 def encrypt_payment_pwd(payment_pwd):
  return ''.join(['u3' + x for x in payment_pwd])
 # 校驗(yàn)支付密碼
 if len(payment_pwd) > 0:
  data['submitOrderParam.payPassword'] = encrypt_payment_pwd(payment_pwd)
 # 請(qǐng)求報(bào)文頭
 headers = {
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
  "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
  "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
  "Connection": "keep-alive",
  'Host': 'trade.jd.com',
 }
 # 訂單提交會(huì)嘗試兩次
 for count in range(1, 3):
  logger.info('第[%s/%s]次嘗試提交訂單', count, 3)
  try:
   # 可能會(huì)存在的校驗(yàn)碼
   if is_Submit_captcha:
    captcha_result = page_detail_captcha(session, encryptClientInfo)
    # 驗(yàn)證碼服務(wù)錯(cuò)誤
    if not captcha_result:
     logger.error('驗(yàn)證碼服務(wù)異常')
     continue
    data['submitOrderParam.checkcodeTxt'] = submit_captcha_text
    data['submitOrderParam.checkCodeRid'] = submit_captcha_rid
   # 提交訂單
   resp = session.post(url=url, data=data, headers=headers)
   resp_json = json.loads(resp.text)
   logger.info('本次提交訂單耗時(shí)[%s]毫秒', str(int(time.time() * 1000) - submit_Time))
   # 判斷是否提交成功
   if resp_json.get('success'):
    logger.info('訂單提交成功! 訂單號(hào):%s', resp_json.get('orderId'))
    return True
   else:
    # 提交失敗返回的多種原因
    resultMessage, result_code = resp_json.get('message'), resp_json.get('resultCode')
    if result_code == 0:
     # self._save_invoice()
     if '驗(yàn)證碼不正確' in resultMessage:
      resultMessage = resultMessage + '(驗(yàn)證碼錯(cuò)誤)'
      logger.info('提交訂單驗(yàn)證碼[錯(cuò)誤]')
      continue
     else:
      resultMessage = resultMessage + '(下單商品可能為第三方商品,將切換為普通發(fā)票進(jìn)行嘗試)'
    elif result_code == 60077:
     resultMessage = resultMessage + '(可能是購(gòu)物車為空 或 未勾選購(gòu)物車中商品)'
    elif result_code == 60123:
     resultMessage = resultMessage + '(需要在payment_pwd參數(shù)配置支付密碼)'
    elif result_code == 60070:
     resultMessage = resultMessage + '(省份不支持銷售)'
     skuids.remove(sku_id)
     logger.info('[%s]類型口罩不支持銷售', sku_id)
    logger.info('訂單提交失敗, 錯(cuò)誤碼:%s, 返回信息:%s', result_code, resultMessage)
    logger.info(resp_json)
    return False
  except Exception as e:
   print(traceback.format_exc())
   continue

關(guān)于“如何使用Python在京東上搶口罩”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI