618 | 如何用Python腳本實現(xiàn) 京東自動保價

來源:Python 技術(shù)「ID: pythonall」
大家在 618 一定買了很多東西,而有些商家喜歡偷偷摸摸降價讓我們覺得瞬間虧了一個億。今天就擼一個京東的自動保價腳本。
一、獲取保價列表
首先需要登錄京東,這個在 《618!京東PC版搶卷》上寫過了,是使用二維碼登錄的,大家可以看看。
打開京東保價頁面(https://pcsitepp-fm.jd.com/),需要獲取到下圖紅框中的元素,有名稱,數(shù)量,購買價格。

按 F12 獲取下頁面元素

先把全局的變量放在前面
user_agent?=?'Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_15_4)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/81.0.4044.138?Safari/537.36'
session?=?requests.session()
下面的代碼獲取可以保價的訂單列表包含訂單號和商品的 sku 號和數(shù)量,有 3 個函數(shù),get_pin() 函數(shù)獲取 PIN 值,get_order_list() 函數(shù)循環(huán)獲取訂單列表,skuProResultPC() 函數(shù)判斷這個訂單是否超了保價時間
def?get_pin():
????"""獲取?PIN,用正則表達式從頁面中取出"""
????url?=?"https://pcsitepp-fm.jd.com/"
????r?=?session.get(url)
????loginPin?=?re.findall('',?r.text)
????pin?=?loginPin[0]?if?len(loginPin)?>?0?else?None
????return?pin
def?get_order_list(pin,?page_num=1):
????"""保價列表"""
????#?存放訂單信息
????order_info?=?[]
????#?存放數(shù)量
????count_dir?=?{}
????url?=?"https://pcsitepp-fm.jd.com/rest/pricepro/priceskusPull"
????data?=?{"page":?page_num,?"pageSize":?10}
????headers?=?{
????????'User-Agent':?user_agent,
????????'Referer':?'https://pcsitepp-fm.jd.com/',
????}
????r?=?session.post(url,?headers=?headers,?data=data)
????#?訂單之間的分隔符
????orders?=?r.text.split(' ')
????orders.pop(0)
????for?item?in?orders:
????????#?訂單號
????????orderid?=?re.findall("訂單號:(\d+)",?item)
????????#?數(shù)量
????????count?=?re.findall('\n([\sx\d]+)',item)
????????#?商品的?sku和序號
????????skuidAndSequences?=?re.findall("queryOrderSkuPriceParam\.skuidAndSequence\.push\(\"(\d+\,\d+)\"\)\;",?item)
????????newSkuidAndSequences?=?[]
????????#?商品的sku和訂單商品的序號
????????for?ss?in?skuidAndSequences:
????????????#?判斷訂單保價是否超時
????????????if?skuProResultPC(orderid[0],?ss.split(',')[0],?pin):
????????????????newSkuidAndSequences.append(ss)
????????????????if?orderid[0]?==?'117403228624':
????????????????????print(orderid[0])
????????????????count_ss?=?count_html[int(ss.split(',')[1])?-?1]
????????????????count?=?count_ss.replace('\t',?'').replace('\n',?'').replace('x',?'')
????????????????#?把?"訂單號_sku"?當做?key
????????????????count_dir[orderid[0]?+?'_'?+?ss.split(',')[0]]?=?count
????????if?newSkuidAndSequences:
????????????order_info.append({'orderid':?orderid[0],?'skuidAndSequence':?newSkuidAndSequences})
????if?orders:
????????"""遞歸的方式獲取所有的商品"""
????????bill_info_sub,?count_dir_sub?=?get_order_list(pin,?page_num?+?1)
????????order_info.extend(bill_info_sub)
????????count_dir.update(count_dir_sub)
????return?order_info,?count_dir
def?skuProResultPC(orderId,?skuId,?pin):
????"""判斷訂單是否保價超時"""
????url?=?"https://sitepp-fm.jd.com/rest/webserver/skuProResultPC"
????data?=?{
????????"orderId":?orderId,
????????"skuId":?skuId,
????????"pin":?pin
????}
????headers?=?{
????????'User-Agent':?user_agent,
????????'Referer':?'https://pcsitepp-fm.jd.com/',
????}
????r?=?session.post(url,?data=data,?headers=headers)
????return?'overTime'?not?in?r.text
示例結(jié)果
訂單信息:
[{'orderid':?'118598307636',?'skuidAndSequence':?['851267,1']},?{'orderid':?'118597642910',?'skuidAndSequence':?['4389188,1']},?{'orderid':?'123625659522',?'skuidAndSequence':?['69699954984,1']},?{'orderid':?'123539553604',?'skuidAndSequence':?['6839875,1']},?{'orderid':?'123474129967',?'skuidAndSequence':?['50000970588,1']}]
商品數(shù)量
{'118598307636_851267':?'10',?'118597642910_4389188':?'10',?'123625659522_69699954984':?'1',?'123539553604_6839875':?'4',?'123474129967_50000970588':?'1',?'122842702447_31295640649':?'1',?'117403228624_31295640649':?'1'}
二、商品信息
在獲取保價列表中,已經(jīng)取到了商品的 sku 號,在商品 url(如:https://item.jd.com/6839875.html)中最后的數(shù)字便是 sku 號,利用 sku 號可以獲取到商品信息。

分析元素可知在頁面的 js 中,pageConfig 變量有我們需要的所有數(shù)據(jù),用正則表達式取出

def?get_product_info(skuId):
????"""獲商品信息"""
????info?=?{}
????url?=?"http://item.jd.com/%s.html"?%?skuId
????headers?=?{
????????'User-Agent':?user_agent,
????????'Referer':?'https://pcsitepp-fm.jd.com/',
????}
????r?=?requests.get(url,?headers=headers)
????pageConfig?=?re.findall("var?pageConfig?=?\{([\s\S]+)\}?catch\(e\)?\{\}",?r.text)
????cat?=?re.findall("cat:?\[([\d,]+)\]",?pageConfig[0])
????venderId?=?re.findall("venderId:(\d+)",?pageConfig[0])
????shopId?=?re.findall("shopId:'(\d+)'",?pageConfig[0])
????name?=?re.findall("name:?'(.+)'",?pageConfig[0])
????info['cat']?=?cat[0]?if?len(cat)?else?""
????info['venderId']?=?venderId[0]?if?len(venderId)?else?""
????info['shopId']?=?shopId[0]?if?len(shopId)?else?""
????info['skuId']?=?skuId
????#?配送區(qū)域默認為北京
????info['area']?=?'1_72_55653_0'?
????info['name']?=?name[0]
????return?info
示例結(jié)果
{'cat':?'1319,1525,7057',?'venderId':?'1000015389',?'shopId':?'1000015389',?'skuId':?'6839875',?'area':?'1_72_55653_0',?'name':?'雀氏chiaus薄c引力紙尿褲小號S27片(4-8kg)尿不濕新生兒柔薄透氣'}
{'cat':?'1319,6313,15614',?'venderId':?'10109166',?'shopId':?'965779',?'skuId':?'50000970588',?'area':?'1_72_55653_0',?'name':?'七彩博士?嬰兒定型枕0-1歲?夏季透氣天絲新生兒乳膠枕頭寶寶U型枕新生兒用品?綠色天絲枕'}
{'cat':?'1319,1527,1559',?'venderId':?'107952',?'shopId':?'106328',?'skuId':?'31295640649',?'area':?'1_72_55653_0',?'name':?'babycare嬰兒紙巾抽紙新生兒面巾紙云柔巾寶寶紙巾?108抽*6包'}
三、商品當前價格
獲取到商品信息后,把這些數(shù)據(jù)當做參數(shù)提交到 url(https://c0.3.cn/stock)中獲取商品當前的價格。
def?get_product_price(product_info):
????url?=?"https://c0.3.cn/stock?skuId={}&area={}&venderId={}&buyNum=1&choseSuitSkuIds=&cat={}&extraParam={{%22originid%22:%221%22}}&fqsp=0&ch=1&callback=jQuery{}"\
????????.format(product_info['skuId'],?
????????????????product_info['area'],?
????????????????product_info['venderId'],?
????????????????product_info.get('cat',?''),?
????????????????random.randint(1000000,?9999999))
????headers?=?{
????????'User-Agent':?user_agent,
????????'Host':?'c0.3.cn',
????????'Referer':??'https://item.jd.com/{0}.html'.format(product_info['skuId']),
????}
????r?=?session.get(url,?headers=headers)
????data?=?parse_json(r.text)
????#?價格
????price?=?data.get("stock",?{}).get("jdPrice",?{}).get('p',?0)
????return?float(price)
四、商品可用優(yōu)惠券
在京東購物經(jīng)常有滿 xx 減 xx 和 滿 xx 打 xx 折的優(yōu)惠券,當購買商品時未使用優(yōu)惠券,可以聯(lián)系客服進行價格保護,這里抓取優(yōu)惠券并打印出來

def?get_product_coupon(product_info,?price):
????"""優(yōu)惠券列表"""
????result?=?[]
????headers?=?{
????????'User-Agent':?user_agent,
????????'Referer':??'https://item.jd.com/{0}.html'.format(product_info['skuId']),
????}
????url?=?'https://cd.jd.com/promotion/v2?callback=jQuery{}&skuId={}&area={}&shopId={}&venderId={}&cat={}&isCanUseDQ=1&isCanUseJQ=1&platform=0&orgType=2&jdPrice={}&appid=1&_={}'\
????????.format(
????????????????str(random.randint(1000000,?9999999)),
????????????????product_info['skuId'],
????????????????product_info['area'],
????????????????product_info['shopId'],
????????????????product_info['venderId'],
????????????????product_info['cat'].replace(',',?'%2C'),
????????????????price,
????????????????str(int(time.time()?*?1000)))
????r?=?session.get(url,?headers=headers)
????data?=?parse_json(r.text)
????pickOneTag?=?data.get("prom",?{}).get("pickOneTag")
????#?滿減
????if?pickOneTag:
????????for?tag?in?pickOneTag:
????????????result.append(tag.get('content'))
????#?打折
????skuCoupon?=?data.get('skuCoupon')
????if?skuCoupon:
????????for?coupon?in?skuCoupon:
????????????if?coupon.get('allDesc'):
????????????????result.append(coupon.get('allDesc'))
????????????elif?coupon.get('quota')?and?coupon.get('discount'):
????????????????result.append("滿"?+?str(coupon.get('quota'))?+?'減'?+?str(coupon.get('discount')))
????return?result
示例結(jié)果
['每滿199元,可減100元現(xiàn)金,最多可減1000元',?'滿3件,總價打5折',?'滿105.0減5.0']
五、下單價格
到這里已經(jīng)取到了商品的當前價格、優(yōu)惠券和購買數(shù)量,還剩下訂單的下單價格需要獲取,這個價格就是第一張圖中的金額。我們使用訂單號和 sku 號作為參數(shù),批量查詢下單價格

def?get_price_list(pin):
????'''獲取下單價格、商品信息、當前價格、數(shù)量'''
????product_list?=?[]
????#?取訂單號,sku和商品數(shù)量
????queryOrderPriceParam,count_dir?=?get_order_list(pin)
????#?獲取購買時的價格
????params?=?{"queryOrderPriceParam":?json.dumps(queryOrderPriceParam)}
????r?=?session.post("https://sitepp-fm.jd.com/rest/webserver/getOrderListSkuPrice",?data?=?params)
????orderList?=?r.json()
????for?item?in?orderList:
????????skuid?=?item.get("skuid")
????????buyingjdprice?=?item.get("buyingjdprice")
????????orderid?=?item.get("orderid")
????????#?商品信息
????????product_info?=?get_product_info(skuid)
????????#?當前價格
????????price?=?get_product_price(product_info)
????????#?優(yōu)惠券
????????coupon?=?get_product_coupon(product_info,?price)
????????name?=?product_info['name']
????????count?=?count_dir[orderid?+?'_'?+?skuid]
????????product_list.append({'orderid':?orderid,?'name':?name,?'price':?price,?'coupon':?coupon,?'count':?count,?'buyingjdprice':?buyingjdprice})
????return?product_list
示例結(jié)果
[{'orderid': '123539553604', 'name': '雀氏chiaus薄c引力紙尿褲小號S27片(4-8kg)尿不濕新生兒柔薄透氣', 'price': 27.9, 'coupon': ['購買1件可優(yōu)惠換購熱銷商品', '滿105.0減5.0', '滿199減50', '滿268減60'], 'count': '4', 'buyingjdprice': 27.0}, {'orderid': '123474129967', 'name': '七彩博士 嬰兒定型枕0-1歲 夏季透氣天絲新生兒乳膠枕頭寶寶U型枕新生兒用品 綠色天絲枕', 'price': 69.0, 'coupon': ['06月16日 00:00 該商品參加跨店鋪滿折活動 ,滿2件,總價打8折;滿3件,總價打7折', '滿98減5', '滿105.0減5.0', '滿178減10'], 'count': '1', 'buyingjdprice': 66.0}]
六、申請價格保護
最后一步比價和申請價格保護,這里分為 2 種情況,一種是當前不能用優(yōu)惠券可以直接申請價格保護,另一種是當前存在優(yōu)惠券,可以打印到控制臺通知用戶。
def?protect_protect_apply(product_list):
????"""申請價格保護"""
????if?len(product_list)?==?0:
????????return
????else:
????????for?item?in?product_list:
????????????result?=?'訂單號:{},名稱:{}, 數(shù)量:{}, 購買價格:{}, 當前價格:{}, 當前優(yōu)惠:{}。'\
????????????????.format(item['orderid'],
????????????????????????item['name'],
????????????????????????item['count'],
????????????????????????item['buyingjdprice'],
????????????????????????item['price'],
????????????????????????'?|?'.join(item['coupon']))
????????????#?沒有優(yōu)惠券并且購買價格高于當前價格
????????????if?len(item['coupon'])?==?0?and?item['buyingjdprice']?>?item['price']:
????????????????url?=?'https://pcsitepp-fm.jd.com//rest/pricepro/skuProtectApply'
????????????????data?=?{
????????????????????"orderId":?item['orderId'],
????????????????????"orderCategory":?"Others",
????????????????????"skuId":?item['skuId'],
????????????????????"refundtype":?1
????????????????}
????????????????headers?=?{
????????????????????'User-Agent':?user_agent,
????????????????????'Referer':?'https://pcsitepp-fm.jd.com/',
????????????????????'accept':?'application/json,?text/javascript,?*/*;?q=0.01'
????????????????}
????????????????session.post(url,?data=data,?headers=headers)
????????????????print(result?+?'?已申請價格保護,請結(jié)果查看價格保護頁面')
????????????elif?len(item['coupon'])?>?0:
????????????????print(result?+?'?在優(yōu)惠券未申請自動價格保護,請聯(lián)系客服申請')
????return
示例結(jié)果
訂單號:123539553604,名稱:雀氏chiaus薄c引力紙尿褲小號S27片(4-8kg)尿不濕新生兒柔薄透氣, 數(shù)量:4, 購買價格:27.0, 當前價格:27.9, 當前優(yōu)惠:購買1件可優(yōu)惠換購熱銷商品 | 滿105.0減5.0 | 滿199減50 | 滿268減60。在優(yōu)惠券未申請自動價格保護,請聯(lián)系客服申請
訂單號:123474129967,名稱:七彩博士 嬰兒定型枕0-1歲 夏季透氣天絲新生兒乳膠枕頭寶寶U型枕新生兒用品 綠色天絲枕, 數(shù)量:1, 購買價格:66.0, 當前價格:69.0, 當前優(yōu)惠:06月16日 00:00 該商品參加跨店鋪滿折活動 ,滿2件,總價打8折;滿3件,總價打7折 | 滿98減5 | 滿105.0減5.0 | 滿178減10。在優(yōu)惠券未申請自動價格保護,請聯(lián)系客服申請
總結(jié)
京東自動保價的腳本核心代碼已經(jīng)完成了,大家可以根據(jù)自己的需求更改代碼。例如增加計劃任務(wù),發(fā)送郵件而不是打印等等。
源碼:https://github.com/JustDoPython/python-examples/tree/master/moumoubaimifan/jbj
