数え切れないほどの駆け込み購入の試みが失敗した後、販売業者が時々少量の供給を放出することがわかり、それぞれの販売単位に何個あるのかを視覚的に見積もりました。時間。製品在庫を 24 時間監視するスクリプトを作成し、商品の供給元が照会されると、自動的に発注しようとするため、成功の可能性が大幅に高まります。
京東の商品の急ぎ購入は主に 2 つのタイプに分けられます:
予約の急ぎ購入: 注文プロセスと同じポイントで購入できます。通常商品、フラッシュセール商品: 個別のスナップアップインターフェイスと注文プロセス。
もちろん、今回は予約の殺到や在庫切れの注文をターゲットとしています。つまり、全体的な注文プロセスは通常の商品を購入する場合と同じです。
アカウントにログイン→ショッピングカートに入力→スナップする製品を選択→クリックしてチェックアウト→クリックして注文を送信→支払い方法を選択し、支払いを行います
。
著者はパケットをキャプチャできるクライアントを持っていないため、JD.com の WEB インターフェイスを使用してスクリプト プログラムを実装することにしました。
したがって、京東の Web ページでの注文プロセスを分析した後、スクリプト プログラムは 4 つのモジュールに分割されました: アカウント ログイン モジュール、在庫監視モジュール、ショッピング カート管理モジュール、注文管理モジュール。
アカウントのパスワードを使用する場合は確認コードの制限があるため、これを回避するには QR コードをスキャンしてログインします。
スキャン コード ログインに詳しくない、またはスキャン コード ログインに興味がある学生の場合は、スキャン コード ログインの原理と実装に関する Zhou Zhou の以前のブログ投稿を確認してください。
今回は、JD ログイン ページでパケット キャプチャ分析を実行し、いくつかの便利なインターフェイスを見つけるだけです:
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
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']
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']
チケットが有効であることを確認した後、pickle
ライブラリを使用して、次回使用するために、プログラム セッションの Cookie をローカル エリアに保存します。
在庫監視は比較的単純です。商品詳細ページを分析し、ストア 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('获取商品信息失败,请检查SKU是否正确') detail = dict(catId=cat, venderId=vender) return detail
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') # 商品是否上架 # 商品库存状态:33 -- 现货 0,34 -- 无货 36 -- 采购中 40 -- 可配货 stockState = stockInfo.get('StockState') return skuState == 1 and stockState in (33, 40)
在庫切れの商品をこのページからショッピングカートに追加することはできません他の在庫商品を使用してみてください。主にショッピング カートのインターフェイスの追加、削除、変更、確認を確認してください:
def uncheckCartAll(self): """ 取消所有选中商品 return 购物车信息 """ 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
def addCartSku(self, skuId, skuNum): """ 加入购入车 skuId 商品sku skuNum 购买数量 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']
def changeCartSkuCount(self, skuId, skuUid, skuNum, areaId): """ 修改购物车商品数量 skuId 商品sku skuUid 商品用户关系 skuNum 购买数量 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']
上記は必要な最小限のインターフェイスですアカウントのショッピング カート内の既存のデータが破壊されないようにするには、次の手順でショッピング カートの準備を使用します:
すべてのチェックをキャンセルします (ショッピング カートの情報に戻ります)。すでにショッピングカートに入っている場合は数量を、ショッピングカートに入っていない場合はショッピングカートに追加してください。 3.4 注文操作
ショッピング カートの準備 (購入するアイテムの選択と購入数量の調整) が完了したら、次の注文関連操作に進むことができます。決済フォーム
def getCheckoutPage(self): """获取订单结算页面信息 :return: 结算信息 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 订单提交结果 """ 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, }
以上がPython を使用して JD.com で自動的に注文するスクリプトを作成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。