Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /