Skip to content

Commit 69c2c83

Browse files
committed
京东自动保价脚本代码
1 parent 8ea5260 commit 69c2c83

File tree

1 file changed

+317
-0
lines changed

1 file changed

+317
-0
lines changed

moumoubaimifan/jbj/jbj.py

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
import re
2+
3+
import requests
4+
import random
5+
import time
6+
import os
7+
import json
8+
9+
from PIL import Image
10+
11+
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'
12+
13+
session = requests.session()
14+
15+
16+
def show_QRcode():
17+
url = 'https://qr.m.jd.com/show'
18+
params = {
19+
'appid': 133,
20+
'size': 147,
21+
't': str(int(time.time() * 1000)),
22+
}
23+
headers = {
24+
'User-Agent': user_agent,
25+
'Referer': 'https://passport.jd.com/new/login.aspx',
26+
}
27+
resp = session.get(url=url, headers=headers, params=params)
28+
29+
QRcode_path = 'QRcode.png'
30+
with open(QRcode_path, 'wb') as f:
31+
for chunk in resp.iter_content(chunk_size=1024):
32+
f.write(chunk)
33+
34+
QRcode = Image.open(QRcode_path)
35+
QRcode.show()
36+
37+
def check_QRcode():
38+
39+
url = 'https://qr.m.jd.com/check'
40+
params = {
41+
'appid': '133',
42+
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
43+
'token': session.cookies.get('wlfstk_smdl'),
44+
'_': str(int(time.time() * 1000)),
45+
}
46+
headers = {
47+
'User-Agent': user_agent,
48+
'Referer': 'https://passport.jd.com/new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F',
49+
}
50+
resp = session.get(url=url, headers=headers, params=params)
51+
resp_json = parse_json(resp.text)
52+
53+
if 'ticket' in resp_json:
54+
return resp_json['ticket']
55+
else:
56+
print(resp_json['msg'])
57+
print('请刷新JD登录二维码!')
58+
os._exit(0)
59+
60+
61+
def validation_QRcode(ticket):
62+
63+
url = 'https://passport.jd.com/uc/qrCodeTicketValidation'
64+
headers = {
65+
'User-Agent': user_agent,
66+
'Referer': 'https://passport.jd.com/new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F',
67+
}
68+
params={
69+
't': ticket
70+
}
71+
session.get(url=url, headers=headers, params=params)
72+
73+
74+
def parse_json(str):
75+
try:
76+
return json.loads(str[str.find('{'):str.rfind('}') + 1])
77+
except:
78+
str = str.replace('jQuery{}(','')
79+
return json.loads(str[str.find('{'):str.rfind('}') + 1])
80+
81+
def get_pin():
82+
"""获取 PIN,用正则表达式从页面中取出"""
83+
url = "https://pcsitepp-fm.jd.com/"
84+
r = session.get(url)
85+
loginPin = re.findall('<input type="hidden" id="loginPin" value="(\w+)" />', r.text)
86+
pin = loginPin[0] if len(loginPin) > 0 else None
87+
return pin
88+
89+
def skuProResultPC(orderId, skuId, pin):
90+
"""判断订单是否保价超时"""
91+
url = "https://sitepp-fm.jd.com/rest/webserver/skuProResultPC"
92+
data = {
93+
"orderId": orderId,
94+
"skuId": skuId,
95+
"pin": pin
96+
}
97+
headers = {
98+
'User-Agent': user_agent,
99+
'Referer': 'https://pcsitepp-fm.jd.com/',
100+
}
101+
102+
r = session.post(url, data=data, headers=headers)
103+
return 'overTime' not in r.text
104+
105+
def get_order_list(pin, page_num=1):
106+
"""保价列表"""
107+
108+
# 存放订单信息
109+
order_info = []
110+
# 存放数量
111+
count_dir = {}
112+
113+
url = "https://pcsitepp-fm.jd.com/rest/pricepro/priceskusPull"
114+
data = {"page": page_num, "pageSize": 10}
115+
headers = {
116+
'User-Agent': user_agent,
117+
'Referer': 'https://pcsitepp-fm.jd.com/',
118+
}
119+
r = session.post(url, headers= headers, data=data)
120+
121+
# 订单之间的分隔符
122+
orders = r.text.split('<tr class="sep-row"><td colspan="6"></td></tr>')
123+
orders.pop(0)
124+
125+
for item in orders:
126+
# 订单号
127+
orderid = re.findall("订单号:(\d+)", item)
128+
# 数量
129+
count_html = re.findall('<span class="count">([\sx\d]+)</span>',item)
130+
# 商品的 sku和序号
131+
skuidAndSequences = re.findall("queryOrderSkuPriceParam\.skuidAndSequence\.push\(\"(\d+\,\d+)\"\)\;", item)
132+
newSkuidAndSequences = []
133+
134+
# 商品的sku和订单商品的序号
135+
for ss in skuidAndSequences:
136+
137+
# 判断订单保价是否超时
138+
if skuProResultPC(orderid[0], ss.split(',')[0], pin):
139+
140+
newSkuidAndSequences.append(ss)
141+
count_ss = count_html[int(ss.split(',')[1]) - 1]
142+
count = count_ss.replace('\t', '').replace('\n', '').replace('x', '')
143+
# 把 "订单号_sku" 当做 key
144+
count_dir[orderid[0] + '_' + ss.split(',')[0]] = count
145+
146+
if newSkuidAndSequences:
147+
148+
order_info.append({'orderid': orderid[0], 'skuidAndSequence': newSkuidAndSequences})
149+
150+
if orders:
151+
"""递归的方式获取所有的商品"""
152+
bill_info_sub, count_dir_sub = get_order_list(pin, page_num + 1)
153+
order_info.extend(bill_info_sub)
154+
count_dir.update(count_dir_sub)
155+
return order_info, count_dir
156+
157+
def get_price_list(pin):
158+
'''获取下单价格、商品信息、当前价格、数量'''
159+
160+
product_list = []
161+
162+
# 取订单号,sku和商品数量
163+
queryOrderPriceParam,count_dir = get_order_list(pin)
164+
165+
# 获取购买时的价格
166+
params = {"queryOrderPriceParam": json.dumps(queryOrderPriceParam)}
167+
r = session.post("https://sitepp-fm.jd.com/rest/webserver/getOrderListSkuPrice", data = params)
168+
orderList = r.json()
169+
170+
171+
for item in orderList:
172+
173+
skuid = item.get("skuid")
174+
buyingjdprice = item.get("buyingjdprice")
175+
orderid = item.get("orderid")
176+
177+
# 商品信息
178+
product_info = get_product_info(skuid)
179+
# 当前价格
180+
price = get_product_price(product_info)
181+
# 优惠券
182+
coupon = get_product_coupon(product_info, price)
183+
184+
name = product_info['name']
185+
count = count_dir[orderid + '_' + skuid]
186+
product_list.append({'orderid': orderid, 'name': name, 'price': price, 'coupon': coupon, 'count': count, 'buyingjdprice': buyingjdprice})
187+
return product_list
188+
189+
def protect_protect_apply(product_list):
190+
"""申请价格保护"""
191+
192+
if len(product_list) == 0:
193+
return
194+
else:
195+
for item in product_list:
196+
result = '订单号:{},名称:{}, 数量:{}, 购买价格:{}, 当前价格:{}, 当前优惠:{}。'\
197+
.format(item['orderid'],
198+
item['name'],
199+
item['count'],
200+
item['buyingjdprice'],
201+
item['price'],
202+
' | '.join(item['coupon']))
203+
204+
# 没有优惠券并且购买价格高于当前价格
205+
if len(item['coupon']) == 0 and item['buyingjdprice'] > item['price']:
206+
207+
url = 'https://pcsitepp-fm.jd.com//rest/pricepro/skuProtectApply'
208+
data = {
209+
"orderId": item['orderId'],
210+
"orderCategory": "Others",
211+
"skuId": item['skuId'],
212+
"refundtype": 1
213+
}
214+
215+
headers = {
216+
'User-Agent': user_agent,
217+
'Referer': 'https://pcsitepp-fm.jd.com/',
218+
'accept': 'application/json, text/javascript, */*; q=0.01'
219+
}
220+
session.post(url, data=data, headers=headers)
221+
print(result + ' 已申请价格保护,请结果查看价格保护页面')
222+
223+
elif len(item['coupon']) > 0:
224+
print(result + ' 在优惠券未申请自动价格保护,请联系客服申请')
225+
return
226+
227+
228+
229+
230+
def get_product_price(project_info):
231+
232+
url = "https://c0.3.cn/stock?skuId={}&area={}&venderId={}&buyNum=1&choseSuitSkuIds=&cat={}&extraParam={{%22originid%22:%221%22}}&fqsp=0&ch=1&callback=jQuery{}"\
233+
.format(project_info['skuId'],
234+
project_info['area'],
235+
project_info['venderId'],
236+
project_info.get('cat', ''),
237+
random.randint(1000000, 9999999))
238+
headers = {
239+
'User-Agent': user_agent,
240+
'Host': 'c0.3.cn',
241+
'Referer': 'https://item.jd.com/{0}.html'.format(project_info['skuId']),
242+
}
243+
r = session.get(url, headers=headers)
244+
data = parse_json(r.text)
245+
# 价格
246+
price = data.get("stock", {}).get("jdPrice", {}).get('p', 0)
247+
return float(price)
248+
249+
def get_product_info(skuId):
250+
"""获商品信息"""
251+
info = {}
252+
url = "http://item.jd.com/%s.html" % skuId
253+
headers = {
254+
'User-Agent': user_agent,
255+
'Referer': 'https://pcsitepp-fm.jd.com/',
256+
}
257+
r = requests.get(url, headers=headers)
258+
pageConfig = re.findall("var pageConfig = \{([\s\S]+)\} catch\(e\) \{\}", r.text)
259+
cat = re.findall("cat: \[([\d,]+)\]", pageConfig[0])
260+
venderId = re.findall("venderId:(\d+)", pageConfig[0])
261+
shopId = re.findall("shopId:'(\d+)'", pageConfig[0])
262+
name = re.findall("name: '(.+)'", pageConfig[0])
263+
info['cat'] = cat[0] if len(cat) else ""
264+
info['venderId'] = venderId[0] if len(venderId) else ""
265+
info['shopId'] = shopId[0] if len(shopId) else ""
266+
info['skuId'] = skuId
267+
# 配送区域默认为北京
268+
info['area'] = '1_72_55653_0'
269+
info['name'] = name[0]
270+
return info
271+
272+
def get_product_coupon(product_info, price):
273+
"""优惠券列表"""
274+
result = []
275+
headers = {
276+
'User-Agent': user_agent,
277+
'Referer': 'https://item.jd.com/{0}.html'.format(product_info['skuId']),
278+
}
279+
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&_={}'\
280+
.format(
281+
str(random.randint(1000000, 9999999)),
282+
product_info['skuId'],
283+
product_info['area'],
284+
product_info['shopId'],
285+
product_info['venderId'],
286+
product_info['cat'].replace(',', '%2C'),
287+
price,
288+
str(int(time.time() * 1000)))
289+
r = session.get(url, headers=headers)
290+
data = parse_json(r.text)
291+
pickOneTag = data.get("prom", {}).get("pickOneTag")
292+
293+
# 满减
294+
if pickOneTag:
295+
for tag in pickOneTag:
296+
result.append(tag.get('content'))
297+
298+
# 打折
299+
skuCoupon = data.get('skuCoupon')
300+
if skuCoupon:
301+
for coupon in skuCoupon:
302+
if coupon.get('allDesc'):
303+
result.append(coupon.get('allDesc'))
304+
elif coupon.get('quota') and coupon.get('discount'):
305+
result.append("满" + str(coupon.get('quota')) + '减' + str(coupon.get('discount')))
306+
return result
307+
308+
if __name__ == '__main__':
309+
show_QRcode()
310+
time.sleep(10)
311+
ticket = check_QRcode()
312+
validation_QRcode(ticket)
313+
pin = get_pin()
314+
product_list = get_price_list(pin)
315+
protect_protect_apply(product_list)
316+
print("完成了")
317+

0 commit comments

Comments
 (0)