├── Console Version
├── JDAutoBuyTool.py
├── Please fill out this document.txt
├── Please fill out this document.txt.old
├── __pycache__
│ ├── JDAutoBuyTool.cpython-37.pyc
│ ├── JDAutoBuyTool.cpython-38.pyc
│ ├── my_test.cpython-37.pyc
│ └── test.cpython-37.pyc
├── jQuery3078854.dat
├── jQuery3078854.txt
├── jdAutoBuyGood.log
├── my_test.py
├── requirements.txt
├── test.py
└── test2.py
├── GUI Version
├── autobuy.py
├── image
│ ├── down.png
│ ├── left.png
│ └── right.png
├── jdAutoBuyGood.log
├── qr.png
└── window.qss
├── LICENSE
├── README.md
└── assets
├── 1580963259089.png
├── 1580963623908.png
├── 1581038258274.png
├── 1581218076866.png
├── 1581218537205.png
├── 1581249279630.png
├── 1581508416184.png
├── 1581508444771.png
├── 1581768204211.png
├── 1581768213048.png
└── 1583151909197.png
/Console Version/JDAutoBuyTool.py:
--------------------------------------------------------------------------------
1 | # -*- coding=utf-8 -*-
2 | import requests
3 | import logging
4 | import logging.handlers
5 | import time
6 | import json
7 | import sys
8 | import random
9 | from bs4 import BeautifulSoup
10 | import smtplib
11 | import re
12 | import getpass,socket
13 | from email.mime.text import MIMEText
14 | from email.header import Header
15 |
16 | import traceback
17 |
18 |
19 | def setLogger(logFileName, logger):
20 | """ 创建日志文件
21 |
22 |
23 | """
24 | logger.setLevel(logging.INFO)#在logger这个记录器上记录info级别的消息
25 | formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
26 |
27 | console_handler = logging.StreamHandler() #返回日志记录流,这里是输出在终端上
28 | console_handler.setFormatter(formatter)
29 | logger.addHandler(console_handler)
30 |
31 | # 打开指定的文件并将其用作日志记录流
32 | file_handler = logging.handlers.RotatingFileHandler(
33 | logFileName, maxBytes=10485760, backupCount=5, encoding="utf-8")
34 | file_handler.setFormatter(formatter)
35 | logger.addHandler(file_handler)
36 |
37 |
38 | def sendMail(url, isOrder, sendTo):
39 | if len(sendTo) == 0 or sendTo == '$$$$$$$@qq.com':
40 | return
41 |
42 | mailRe = re.compile('^\w{1,15}@\w{1,10}\.(com|cn|net)$')
43 | if not re.search(mailRe, sendTo):
44 | return
45 |
46 | sendFrom = '645064582@qq.com'
47 |
48 | smtp_server = 'smtp.qq.com'
49 | if isOrder:
50 | msg = MIMEText(url + ' 商品已下单, 请在尽快付款', 'plain', 'utf-8')
51 | else:
52 | msg = MIMEText(url + ' 商品下单失败.', 'plain', 'utf-8')
53 |
54 | msg['From'] = Header(sendFrom)
55 | msg['To'] = Header(sendTo)
56 | msg['Subject'] = Header('买到啦')
57 |
58 | server = smtplib.SMTP_SSL(host=smtp_server)
59 | server.connect(smtp_server, 465)
60 | server.login(sendFrom, 'nkrzicfjkzznbehi')
61 | server.sendmail(sendFrom, sendTo, msg.as_string())
62 | server.quit()
63 |
64 |
65 | def sendError(sendTo):
66 | if len(sendTo) == 0 or sendTo == '$$$$$$$@qq.com':
67 | return
68 |
69 | mailRe = re.compile('^\w{1,15}@\w{1,10}\.(com|cn|net)$')
70 | if not re.search(mailRe, sendTo):
71 | return
72 |
73 | sendFrom = '841915343@qq.com'
74 | username = getpass.getuser()
75 | hostname = socket.gethostname()
76 |
77 | # 发信服务器
78 | smtp_server = 'smtp.qq.com'
79 | # 邮箱正文内容, 第一个参数为内容, 第二个参数为格式(plain 为纯文本), 第三个参数为编码
80 | msg = MIMEText('main()函数出错嘞!(from {}.{})\n程序运行时间:{}'.format(hostname,username,time.asctime()), 'plain', 'utf-8')
81 |
82 | # 邮件头信息
83 | msg['From'] = Header(sendFrom)
84 | msg['To'] = Header(sendTo)
85 | msg['Subject'] = Header('ERROR!')
86 | # 开启发信服务, 加密传输
87 | server = smtplib.SMTP_SSL(host=smtp_server)
88 | server.connect(smtp_server, 465)
89 | server.login(sendFrom, 'hqxzxgownfyabfib') #邮箱授权码
90 | server.sendmail(sendFrom, sendTo, msg.as_string())
91 | server.quit()
92 |
93 |
94 | def get_tag_value(tag, key='', index=0):
95 | if key:
96 | value = tag[index].get(key)
97 | else:
98 | value = tag[index].text
99 | return value.strip(' \t\r\n')
100 |
101 |
102 | def responseStatus(resp):
103 | if resp.status_code != requests.codes.OK:
104 | print('Status: %u, Url: %s' % (resp.status_code, resp.url))
105 | return False
106 | return True
107 | def validateCookies(logger, session):
108 | """ 验证cookies并尝试登陆 """
109 | for flag in range(1, 3):
110 | try:
111 | targetURL = 'https://order.jd.com/center/list.action' #这是京东订单页面
112 | payload = {
113 | 'rid': str(int(time.time() * 1000)) #时间戳
114 | }
115 | resp = session.get(url=targetURL, params=payload, allow_redirects=False)
116 | if resp.status_code == requests.codes.OK:
117 | logger.info('登录成功!')
118 | return True
119 | else:
120 | logger.info('第[%s]次请重新获取cookie...', flag)
121 | time.sleep(5)
122 | continue
123 | except Exception as e:
124 | logger.info('第[%s]次请重新获取cookie...', flag)
125 | time.sleep(5)
126 | continue
127 |
128 |
129 | def getUsername(logger, session):
130 | userName_Url = 'https://passport.jd.com/new/helloService.ashx?callback=jQuery339448&_=' + str(
131 | int(time.time() * 1000))
132 | session.headers = {
133 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
134 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
135 | "Referer": "https://order.jd.com/center/list.action",
136 | "Connection": "keep-alive"
137 | }
138 | resp = session.get(url=userName_Url, allow_redirects=True)
139 | resultText = resp.text
140 | resultText = resultText.replace('jQuery339448(', '')
141 | resultText = resultText.replace(')', '')
142 | usernameJson = json.loads(resultText)
143 | logger.info('登录账号名称: ' + usernameJson['nick'])
144 |
145 |
146 | def cancelSelectCartItem(session):
147 | url = "https://cart.jd.com/cancelAllItem.action"
148 | data = {
149 | 't': 0,
150 | 'outSkus': '',
151 | 'random': random.random()
152 | }
153 | resp = session.post(url, data=data)
154 | if resp.status_code != requests.codes.OK:
155 | print('Status: %u, Url: %s' % (resp.status_code, resp.url))
156 | return False
157 | return True
158 |
159 | def cart_detail(session, logger, isOutput=False):
160 | url = 'https://cart.jd.com/cart.action'
161 | headers = {
162 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
163 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
164 | "Referer": "https://order.jd.com/center/list.action",
165 | "Host": "cart.jd.com",
166 | "Connection": "keep-alive"
167 | }
168 | resp = session.get(url, headers=headers)
169 | soup = BeautifulSoup(resp.text, "html.parser")
170 |
171 | cartDetail = dict()
172 | for item in soup.find_all(class_='item-item'):
173 | sku_id = item['skuid'] # 商品id
174 | try:
175 | # 例如: ['increment', '8888', '100001071956', '1', '13', '0', '50067652554']
176 | # ['increment', '8888', '100002404322', '2', '1', '0']
177 | item_attr_list = item.find(class_='increment')['id'].split('_')
178 | p_type = item_attr_list[4]
179 | promo_id = target_id = item_attr_list[-1] if len(item_attr_list) == 7 else 0
180 |
181 | cartDetail[sku_id] = {
182 | 'name': get_tag_value(item.select('div.p-name a')), # 商品名称
183 | 'verder_id': item['venderid'], # 商家id
184 | 'count': int(item['num']), # 数量
185 | 'unit_price': get_tag_value(item.select('div.p-price strong'))[1:], # 单价
186 | 'total_price': get_tag_value(item.select('div.p-sum strong'))[1:], # 总价
187 | 'is_selected': 'item-selected' in item['class'], # 商品是否被勾选
188 | 'p_type': p_type,
189 | 'target_id': target_id,
190 | 'promo_id': promo_id
191 | }
192 | except Exception as e:
193 | logger.error("商品%s在购物车中的信息无法解析, 报错信息: %s, 该商品自动忽略", sku_id, e)
194 |
195 | if isOutput == True:
196 | logger.info('当前购物车信息: %s', cartDetail)
197 | return cartDetail
198 |
199 | def change_item_num_in_cart(sku_id, vender_id, num, p_type, target_id, promo_id, session):
200 | url = "https://cart.jd.com/changeNum.action"
201 | data = {
202 | 't': 0,
203 | 'venderId': vender_id,
204 | 'pid': sku_id,
205 | 'pcount': num,
206 | 'ptype': p_type,
207 | 'targetId': target_id,
208 | 'promoID': promo_id,
209 | 'outSkus': '',
210 | 'random': random.random(),
211 | # 'locationId'
212 | }
213 | session.headers = {
214 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
215 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
216 | "Referer": "https://cart.jd.com/cart",
217 | "Connection": "keep-alive"
218 | }
219 | resp = session.post(url, data=data)
220 | return json.loads(resp.text)['sortedWebCartResult']['achieveSevenState'] == 2
221 |
222 |
223 | def addItemToCart(sku_id, session, logger):
224 | url = 'https://cart.jd.com/gate.action'
225 | payload = {
226 | 'pid': sku_id,
227 | 'pcount': 1,
228 | 'ptype': 1,
229 | }
230 | resp = session.get(url=url, params=payload)
231 | if 'https://cart.jd.com/cart.action' in resp.url: # 套装商品加入购物车后直接跳转到购物车页面
232 | result = True
233 | else: # 普通商品成功加入购物车后会跳转到提示 "商品已成功加入购物车!" 页面
234 | soup = BeautifulSoup(resp.text, "html.parser")
235 | result = bool(soup.select('h3.ftx-02')) # [
商品已成功加入购物车!
]
236 |
237 | if result:
238 | logger.info('%s 已成功加入购物车', sku_id)
239 | else:
240 | logger.error('%s 添加到购物车失败', sku_id)
241 |
242 |
243 | def get_checkout_page_detail(session, logger):
244 | url = 'http://trade.jd.com/shopping/order/getOrderInfo.action'
245 | # url = 'https://cart.jd.com/gotoOrder.action'
246 | payload = {
247 | 'rid': str(int(time.time() * 1000)),
248 | }
249 | headers = {
250 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
251 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
252 | "Referer": "https://cart.jd.com/cart.action",
253 | "Connection": "keep-alive",
254 | 'Host': 'trade.jd.com',
255 | }
256 | try:
257 | resp = session.get(url=url, params=payload, headers=headers)
258 | if not responseStatus(resp):
259 | logger.error('获取订单结算页信息失败')
260 | return ''
261 |
262 | soup = BeautifulSoup(resp.text, "html.parser")
263 | risk_control = get_tag_value(soup.select('input#riskControl'), 'value')
264 |
265 | order_detail = {
266 | 'address': soup.find('span', id='sendAddr').text[5:], # remove '寄送至: ' from the begin
267 | 'receiver': soup.find('span', id='sendMobile').text[4:], # remove '收件人:' from the begin
268 | 'total_price': soup.find('span', id='sumPayPriceId').text[1:], # remove '¥' from the begin
269 | 'items': []
270 | }
271 |
272 | logger.info("下单信息: %s", order_detail)
273 | return order_detail
274 | except requests.exceptions.RequestException as e:
275 | logger.error('订单结算页面获取异常: %s' % e)
276 | except Exception as e:
277 | logger.error('下单页面数据解析异常: %s', e)
278 | return None
279 |
280 |
281 | def submit_order(risk_control, session, logger, payment_pwd):
282 | url = 'https://trade.jd.com/shopping/order/submitOrder.action'
283 | # js function of submit order is included in https://trade.jd.com/shopping/misc/js/order.js?r=2018070403091
284 |
285 | # overseaPurchaseCookies:
286 | # vendorRemarks: []
287 | # submitOrderParam.sopNotPutInvoice: false
288 | # submitOrderParam.trackID: TestTrackId
289 | # submitOrderParam.ignorePriceChange: 0
290 | # submitOrderParam.btSupport: 0
291 | # riskControl:
292 | # submitOrderParam.isBestCoupon: 1
293 | # submitOrderParam.jxj: 1
294 | # submitOrderParam.trackId:
295 |
296 | data = {
297 | 'overseaPurchaseCookies': '',
298 | 'vendorRemarks': '[]',
299 | 'submitOrderParam.sopNotPutInvoice': 'false',
300 | 'submitOrderParam.trackID': 'TestTrackId',
301 | 'submitOrderParam.ignorePriceChange': '0',
302 | 'submitOrderParam.btSupport': '0',
303 | 'riskControl': risk_control,
304 | 'submitOrderParam.isBestCoupon': 1,
305 | 'submitOrderParam.jxj': 1,
306 | 'submitOrderParam.trackId': '9643cbd55bbbe103eef18a213e069eb0', # Todo: need to get trackId
307 | # 'submitOrderParam.eid': eid,
308 | # 'submitOrderParam.fp': fp,
309 | 'submitOrderParam.needCheck': 1,
310 | }
311 |
312 | def encrypt_payment_pwd(paymentPwd):
313 | return ''.join(['u3' + x for x in paymentPwd])
314 |
315 | if len(payment_pwd) > 0:
316 | data['submitOrderParam.payPassword'] = encrypt_payment_pwd(payment_pwd)
317 |
318 | headers = {
319 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
320 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
321 | "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
322 | "Connection": "keep-alive",
323 | 'Host': 'trade.jd.com',
324 | }
325 |
326 | try:
327 | resp = session.post(url=url, data=data, headers=headers)
328 | resp_json = json.loads(resp.text)
329 |
330 | if resp_json.get('success'):
331 | logger.info('订单提交成功! 订单号: %s', resp_json.get('orderId'))
332 | return True
333 | else:
334 | message, result_code = resp_json.get('message'), resp_json.get('resultCode')
335 | if result_code == 0:
336 | # self._save_invoice()
337 | message = message + '(下单商品可能为第三方商品, 将切换为普通发票进行尝试)'
338 | elif result_code == 60077:
339 | message = message + '(可能是购物车为空或未勾选购物车中商品)'
340 | elif result_code == 60123:
341 | message = message + '(未配置支付密码)'
342 | logger.info('订单提交失败, 错误码: %s, 返回信息: %s', result_code, message)
343 | logger.info(resp_json)
344 | return False
345 | except Exception as e:
346 | logger.error(e)
347 | return False
348 |
349 |
350 | def item_removed(sku_id):
351 | """
352 | 判断商品是否下架,若商品未下架,返回真
353 | """
354 | headers = {
355 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
356 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
357 | "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
358 | "Connection": "keep-alive",
359 | 'Host': 'trade.jd.com',
360 | }
361 | url = 'https://item.jd.com/{}.html'.format(sku_id)
362 | page = requests.get(url=url, headers=headers)
363 | return '该商品已下柜' not in page.text
364 |
365 |
366 | def buyGood(sku_id, session, logger, payment_pwd):
367 | for count in range(1, 5):
368 | logger.info('第[%s/%s]次尝试提交订单', count, 5)
369 | cancelSelectCartItem(session)
370 | cart = cart_detail(session, logger)
371 | if sku_id not in cart:
372 | addItemToCart(sku_id, session, logger)
373 | cart_detail(session, logger, True)
374 |
375 | risk_control = get_checkout_page_detail(session, logger)
376 | if len(risk_control) > 0:
377 | if submit_order(risk_control, session, logger, payment_pwd):
378 | return True
379 | logger.info('等待%ss', 3)
380 | time.sleep(3)
381 | else:
382 | logger.info('执行结束, 提交订单失败!')
383 | return False
384 |
385 | def main(sendTo, cookies_String, url):
386 | print("main函数开始运行!")
387 | session = requests.session()
388 | session.headers = {
389 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
390 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=1.8,application/signed-exchange;v=b3",
391 | "Connection": "keep-alive"
392 | }
393 |
394 | logFileName = 'jdAutoBuyGood.log'
395 | logger = logging.getLogger()
396 | setLogger(logFileName, logger)
397 |
398 | manual_cookies = {}
399 | for item in cookies_String.split(';'):
400 | # 用=号分割.
401 | name, value = item.strip().split('=', 1)
402 | manual_cookies[name] = value
403 | # if __name__ == "__main__":
404 | # print("manual_cookies = \n",manual_cookies)
405 | cookiesJar = requests.utils.cookiejar_from_dict(manual_cookies, cookiejar=None, overwrite=True)
406 | session.cookies = cookiesJar
407 | # if __name__ == "__main__":
408 | # print("session.cookies = \n",session.cookies)
409 | # print("manual_coolies = {}\n".format(manual_cookies))
410 | # sys.exit("测试结束!")
411 |
412 | payment_pwd = ''
413 | flag = 1
414 | while (1):
415 | try:
416 | if flag == 1:
417 | validateCookies(logger, session)
418 | getUsername(logger, session)
419 | checkSession = requests.Session()
420 | checkSession.headers = {
421 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
422 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
423 | "Connection": "keep-alive"
424 | }
425 | logger.info('第' + str(flag) + '次 查询...')
426 | flag += 1
427 | for i in url:
428 | # 商品url,skuid是商品编号
429 | skuId = i.split('skuIds=')[1].split('%2C')[2]
430 | skuidUrl = 'https://item.jd.com/' + skuId + '.html'
431 | response = checkSession.get(i)
432 | #一个商品url中实际上有一种商品的多种不同规格的货号
433 | tmp = response.text.split(str(skuId))[1]
434 | m = tmp.find('{')
435 | n = tmp.find('}')
436 | tmp = tmp[m:n+1]
437 | # print(skuId,tmp)
438 | # sys.exit('测试结束!')
439 | if (tmp.find('无货') > 0):
440 | logger.info('[%s]商品无货.', skuId)
441 | else:
442 | if item_removed(skuId):
443 | logger.info('[%s]商品有货啦! 马上下单...', skuId)
444 | if buyGood(skuId, session, logger, payment_pwd):
445 | sendMail(skuidUrl, True, sendTo)
446 | sys.exit(1)
447 | else:
448 | sendMail(skuidUrl, False, sendTo)
449 | sys.exit(1)
450 | else:
451 | logger.info('[%s]商品有货, 但已下架.', skuId)
452 | time.sleep(5)
453 | if flag % 20 == 0:
454 | logger.info('校验是否还在登录...')
455 | validateCookies(logger, session)
456 | except Exception as e:
457 | print(traceback.format_exc())
458 | time.sleep(10)
459 |
460 |
461 | if __name__ == '__main__': #当一个模块被直接运行时,内置变量__name__==‘__main__’,
462 | sendTo = '' #邮箱
463 | cookies_String = '' #用户登陆cookies
464 | fp = open("./Please fill out this document.txt", 'r', encoding='utf-8')
465 | cont = fp.read()
466 | pattern = re.compile("'(.*)'")
467 | contRe = pattern.findall(cont)
468 | if len(contRe) >= 2:
469 | sendTo = contRe[0]
470 | cookies_String = contRe[1]
471 | print("Please confirm the email address: %s" % sendTo)
472 | if len(cookies_String) == 0:
473 | print("ERROR: Missing cookie.")
474 | contRe = contRe[2:] #商品url
475 | print(contRe)
476 | try:
477 | main(sendTo, cookies_String, contRe)
478 | except Exception:
479 | sendError(sendTo) #有异常就发消息到邮箱
--------------------------------------------------------------------------------
/Console Version/Please fill out this document.txt:
--------------------------------------------------------------------------------
1 | 请注意所有讯息在单引号内填写
2 | 您接收下单成功讯息的邮箱(可不填): 'chjxg3@yeah.net'
3 |
4 | 您的登录cookie(请按照README.md内指南获取):
5 | '__jdv=122270672|direct|-|none|-|1605468694100; pinId=mtHyqkrb05E; pin=chjxg3; unick=%E9%87%91%E8%AF%BA1099; _tp=QuoZkycTxuXFYHPqSvJoqA%3D%3D; _pst=chjxg3; PCSYCityID=CN_420000_0_0; shshshfp=799b93d7a8807c25492100e285d0bd55; shshshfpa=1afbb246-5bbf-b0e4-eb19-ca7428a239c2-1605468794; shshshfpb=d4w%2FZW%208KFMTtNlOBKqY1jQ%3D%3D; areaId=17; user-key=3a193397-5d55-4c21-8176-e2568fc8820e; ceshi3.com=000; ipLoc-djd=17-1387-1393-43304.2396251004; ipLocation=%u6e56%u5317; cn=0; __jdc=122270672; 3AB9D23F7A4B3C9B=X55747X4MWHQ4YWHGG47EFSXIGUUGSZI5RNEJF3IX4JH265DUXALGYZHETH75UY53DCBJUZ5GHTBGBUEXZSO5Y6R5M; __jda=122270672.160546869409921141914.1605468694.1605901316.1605987793.7; wlfstk_smdl=cl1ko0xgq0fych62kmi38d0ruyt472bj; TrackID=1dTf7yzpt9a33kDCVdboPq-Ax9MwWPVeOP5kYKTpB-T_Z49UrpKE0dzmea77r3oxL-0kqEcDOjl1hGl-NbGV2QkrT3tHNdlQbZvamwFXsADU; shshshsID=076c0c0be41510eecd156a03c884dbd6_4_1605989099131; __jdb=122270672.9.160546869409921141914|7.1605987793; thor=E0CB04CC147C275CCCD79D976645470FD65B201FDFD67E98013EC61C97FAB76E470C08F264764C16C34075F2448CFA57F9C7E2C16B983ADFB4897CCE3183E6C50F31425C0CF1C7DA25CDD345A69871F2F5A5F3A3068422EB90AD487702ECAE459DBC22C74C6FA326F6FF069A3BDCBD5C3F63B84834E9B749110E7BA703B219E9'
6 |
7 | 您需要自动购买的商品URL(请按照README.md内指南获取):
8 | 'https://c0.3.cn/stocks?callback=jQuery2435878&type=getstocks&skuIds=1564242%2C868883%2C4708316%2C1003982%2C868884&area=17_1387_1393_43304&_=1605898524364'
--------------------------------------------------------------------------------
/Console Version/Please fill out this document.txt.old:
--------------------------------------------------------------------------------
1 | 请注意所有讯息在单引号内填写
2 | 您接收下单成功讯息的邮箱(可不填): 'chjxg3@yeah.net'
3 |
4 | 您的登录cookie(请按照README.md内指南获取):
5 | 'e2a6650a-bf7e-4ebd-96ee-0dcc94d82157'
6 |
7 | 您需要自动购买的商品URL(请按照README.md内指南获取):
8 |
9 | 'https://c0.3.cn/stock?skuId=1835967&area=16_1362_44319_51500&venderId=1000084390&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery1535213'
10 | 'https://c0.3.cn/stock?skuId=1835968&area=16_1362_44319_51500&venderId=1000084390&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery366840'
11 | 'https://c0.3.cn/stock?skuId=1336984&area=16_1362_44319_51500&venderId=1000078145&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery94700'
12 | 'https://c0.3.cn/stock?skuId=65466451629&area=16_1362_44319_51500&venderId=127922&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery8432226'
13 | 'https://c0.3.cn/stock?skuId=7498169&area=16_1362_44319_51500&venderId=1000128491&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery7323892'
14 | 'https://c0.3.cn/stock?skuId=7263128&area=16_1362_44319_51500&venderId=1000128491&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery9621467'
15 | 'https://c0.3.cn/stock?skuId=4061438&area=16_1362_44319_51500&venderId=1000005584&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery620656'
16 | 'https://c0.3.cn/stock?skuId=65421329578&area=16_1362_44319_51500&venderId=593210&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery4952468'
17 | 'https://c0.3.cn/stock?skuId=100005678825&area=16_1362_44319_51500&venderId=1000090691&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery2192795'
18 | 'https://c0.3.cn/stock?skuId=100005294853&area=16_1362_44319_51500&venderId=1000090691&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery8766944'
19 | 'https://c0.3.cn/stock?skuId=45923412989&area=16_1362_44319_51500&venderId=10066244&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery8072251'
20 | 'https://c0.3.cn/stock?skuId=62830056100&area=16_1362_44319_51500&venderId=10066244&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery599501'
21 | 'https://c0.3.cn/stock?skuId=45006657879&area=16_1362_44319_51500&venderId=10066244&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_77a8935fb872d&pduid=526700225&ch=1&callback=jQuery6257903'
--------------------------------------------------------------------------------
/Console Version/__pycache__/JDAutoBuyTool.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/Console Version/__pycache__/JDAutoBuyTool.cpython-37.pyc
--------------------------------------------------------------------------------
/Console Version/__pycache__/JDAutoBuyTool.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/Console Version/__pycache__/JDAutoBuyTool.cpython-38.pyc
--------------------------------------------------------------------------------
/Console Version/__pycache__/my_test.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/Console Version/__pycache__/my_test.cpython-37.pyc
--------------------------------------------------------------------------------
/Console Version/__pycache__/test.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/Console Version/__pycache__/test.cpython-37.pyc
--------------------------------------------------------------------------------
/Console Version/jQuery3078854.dat:
--------------------------------------------------------------------------------
1 | 'jQuery3078854({"1003982":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"},"868884":{"StockState":34,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"0","channel":1,"StockStateName":"无货","rid":null,"m":"0","sid":"0","rfg":0,"dcId":"183","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"-1000000000","ec":"-1"},"4708316":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"},"1564242":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"},"868883":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"}})'
--------------------------------------------------------------------------------
/Console Version/jQuery3078854.txt:
--------------------------------------------------------------------------------
1 | 'jQuery3078854({"1003982":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"},"868884":{"StockState":34,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"0","channel":1,"StockStateName":"无货","rid":null,"m":"0","sid":"0","rfg":0,"dcId":"183","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"-1000000000","ec":"-1"},"4708316":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"},"1564242":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"},"868883":{"StockState":33,"freshEdi":null,"ab":"-1","ac":"-1","ad":"-1","ae":"-1","skuState":1,"PopType":0,"af":"-1","ag":"-1","sidDely":"101","channel":1,"StockStateName":"现货","rid":null,"m":"0","sid":"101","rfg":0,"dcId":"5","ArrivalDate":"","v":"0","IsPurchase":false,"rn":-1,"eb":"0","ec":"-1"}})'
--------------------------------------------------------------------------------
/Console Version/jdAutoBuyGood.log:
--------------------------------------------------------------------------------
1 | 2020-02-06 13:01:10,916 INFO: 登录成功!
2 | 2020-02-06 13:01:11,168 INFO: 登录账号名称: jd_180519iya
3 | 2020-02-06 13:01:11,173 INFO: 第1次 查询...
4 | 2020-02-06 13:01:11,389 INFO: [1835967]商品无货.
5 | 2020-02-06 13:01:11,583 INFO: [1835968]商品无货.
6 | 2020-02-07 18:13:10,251 INFO: 登录成功!
7 | 2020-02-07 18:13:10,463 INFO: 登录账号名称: jd_180519iya
8 | 2020-02-07 18:13:10,467 INFO: 第1次 查询...
9 | 2020-02-07 18:13:10,699 INFO: [1835967]商品无货.
10 | 2020-02-07 18:13:10,947 INFO: [1835968]商品无货.
11 | 2020-11-12 05:18:35,050 INFO: 登录成功!
12 | 2020-11-12 05:18:35,254 INFO: 登录账号名称: 金诺1099
13 | 2020-11-12 05:18:35,255 INFO: 第1次 查询...
14 | 2020-11-12 05:18:45,267 INFO: 第2次 查询...
15 | 2020-11-12 05:18:55,278 INFO: 第3次 查询...
16 | 2020-11-12 05:19:05,287 INFO: 第4次 查询...
17 | 2020-11-12 05:19:15,300 INFO: 第5次 查询...
18 | 2020-11-12 05:19:25,313 INFO: 第6次 查询...
19 | 2020-11-12 05:19:35,326 INFO: 第7次 查询...
20 | 2020-11-12 05:19:45,338 INFO: 第8次 查询...
21 | 2020-11-12 05:19:55,348 INFO: 第9次 查询...
22 | 2020-11-12 05:20:05,361 INFO: 第10次 查询...
23 | 2020-11-12 05:20:15,371 INFO: 第11次 查询...
24 | 2020-11-12 05:20:25,384 INFO: 第12次 查询...
25 | 2020-11-12 05:20:35,395 INFO: 第13次 查询...
26 | 2020-11-12 05:20:45,407 INFO: 第14次 查询...
27 | 2020-11-12 05:20:55,417 INFO: 第15次 查询...
28 | 2020-11-12 05:21:05,427 INFO: 第16次 查询...
29 | 2020-11-12 05:21:15,437 INFO: 第17次 查询...
30 | 2020-11-12 05:21:25,447 INFO: 第18次 查询...
31 | 2020-11-12 05:21:35,457 INFO: 第19次 查询...
32 | 2020-11-12 05:21:45,467 INFO: 第20次 查询...
33 | 2020-11-12 05:21:55,478 INFO: 第21次 查询...
34 | 2020-11-12 05:22:05,487 INFO: 第22次 查询...
35 | 2020-11-12 05:22:15,497 INFO: 第23次 查询...
36 | 2020-11-12 05:22:25,501 INFO: 第24次 查询...
37 | 2020-11-12 05:22:35,511 INFO: 第25次 查询...
38 | 2020-11-12 05:22:45,521 INFO: 第26次 查询...
39 | 2020-11-12 05:22:55,530 INFO: 第27次 查询...
40 | 2020-11-12 05:23:05,542 INFO: 第28次 查询...
41 | 2020-11-12 05:23:15,554 INFO: 第29次 查询...
42 | 2020-11-12 05:23:25,564 INFO: 第30次 查询...
43 | 2020-11-12 05:23:35,576 INFO: 第31次 查询...
44 | 2020-11-12 05:23:45,588 INFO: 第32次 查询...
45 | 2020-11-12 05:23:55,597 INFO: 第33次 查询...
46 | 2020-11-12 05:24:05,607 INFO: 第34次 查询...
47 | 2020-11-12 05:24:15,617 INFO: 第35次 查询...
48 | 2020-11-12 05:31:09,370 INFO: 登录成功!
49 | 2020-11-12 05:31:09,503 INFO: 登录账号名称: 金诺1099
50 | 2020-11-12 05:31:09,504 INFO: 第1次 查询...
51 | 2020-11-12 05:31:19,513 INFO: 第2次 查询...
52 | 2020-11-12 05:35:24,215 INFO: 登录成功!
53 | 2020-11-12 05:35:24,346 INFO: 登录账号名称: 金诺1099
54 | 2020-11-12 05:35:24,346 INFO: 第1次 查询...
55 | 2020-11-12 05:35:34,357 INFO: 第2次 查询...
56 | 2020-11-16 03:34:03,106 INFO: 第[1]次请重新获取cookie...
57 | 2020-11-16 03:34:08,268 INFO: 第[2]次请重新获取cookie...
58 | 2020-11-16 03:34:13,418 INFO: 登录账号名称: 金诺1099
59 | 2020-11-16 03:34:13,419 INFO: 第1次 查询...
60 | 2020-11-16 03:34:23,429 INFO: 第2次 查询...
61 | 2020-11-16 03:40:55,460 INFO: 登录成功!
62 | 2020-11-16 03:40:55,615 INFO: 登录账号名称: 金诺1099
63 | 2020-11-16 03:40:55,616 INFO: 第1次 查询...
64 | 2020-11-16 03:41:05,628 INFO: 第2次 查询...
65 | 2020-11-16 03:41:15,639 INFO: 第3次 查询...
66 | 2020-11-16 03:41:25,649 INFO: 第4次 查询...
67 | 2020-11-18 03:30:10,596 INFO: 第[1]次请重新获取cookie...
68 | 2020-11-18 03:30:15,746 INFO: 第[2]次请重新获取cookie...
69 | 2020-11-18 03:30:20,909 INFO: 登录账号名称: 金诺1099
70 | 2020-11-18 03:30:20,909 INFO: 第1次 查询...
71 | 2020-11-18 03:30:30,918 INFO: 第2次 查询...
72 | 2020-11-18 03:30:40,928 INFO: 第3次 查询...
73 | 2020-11-18 03:37:10,026 INFO: 登录成功!
74 | 2020-11-18 03:37:10,192 INFO: 登录账号名称: 金诺1099
75 | 2020-11-18 03:37:10,192 INFO: 第1次 查询...
76 | 2020-11-18 03:37:20,204 INFO: 第2次 查询...
77 | 2020-11-18 04:03:31,617 INFO: 登录成功!
78 | 2020-11-18 04:03:31,807 INFO: 登录账号名称: 金诺1099
79 | 2020-11-18 04:03:31,808 INFO: 第1次 查询...
80 | 2020-11-18 04:05:41,188 INFO: 第2次 查询...
81 | 2020-11-20 04:00:17,920 INFO: 第[1]次请重新获取cookie...
82 | 2020-11-20 04:00:23,086 INFO: 第[2]次请重新获取cookie...
83 | 2020-11-20 04:00:28,283 INFO: 登录账号名称: 金诺1099
84 | 2020-11-20 04:00:28,284 INFO: 第1次 查询...
85 | 2020-11-20 04:55:00,369 INFO: 第[1]次请重新获取cookie...
86 | 2020-11-20 04:55:05,537 INFO: 第[2]次请重新获取cookie...
87 | 2020-11-20 04:55:10,697 INFO: 登录账号名称: 金诺1099
88 | 2020-11-20 04:55:10,698 INFO: 第1次 查询...
89 | 2020-11-20 04:55:10,826 INFO: [100016129294]商品无货.
90 | 2020-11-20 04:55:15,832 INFO: 第2次 查询...
91 | 2020-11-20 04:55:15,968 INFO: [100016129294]商品无货.
92 | 2020-11-20 04:55:20,973 INFO: 第3次 查询...
93 | 2020-11-20 04:55:21,172 INFO: [100016129294]商品无货.
94 | 2020-11-20 04:55:26,176 INFO: 第4次 查询...
95 | 2020-11-20 04:55:26,298 INFO: [100016129294]商品无货.
96 | 2020-11-20 05:21:41,854 INFO: 第[1]次请重新获取cookie...
97 | 2020-11-20 05:21:47,018 INFO: 第[2]次请重新获取cookie...
98 | 2020-11-20 05:21:52,446 INFO: 登录账号名称: 金诺1099
99 | 2020-11-20 05:21:52,446 INFO: 第1次 查询...
100 | 2020-11-20 05:21:57,450 INFO: 第2次 查询...
101 | 2020-11-20 05:22:02,453 INFO: 第3次 查询...
102 | 2020-11-20 05:22:07,456 INFO: 第4次 查询...
103 | 2020-11-20 05:22:12,459 INFO: 第5次 查询...
104 | 2020-11-20 05:22:17,463 INFO: 第6次 查询...
105 | 2020-11-20 05:22:22,466 INFO: 第7次 查询...
106 | 2020-11-20 05:22:27,469 INFO: 第8次 查询...
107 | 2020-11-20 05:22:32,474 INFO: 第9次 查询...
108 | 2020-11-20 05:22:37,479 INFO: 第10次 查询...
109 | 2020-11-20 05:22:42,485 INFO: 第11次 查询...
110 | 2020-11-20 05:22:47,489 INFO: 第12次 查询...
111 | 2020-11-20 05:22:52,495 INFO: 第13次 查询...
112 | 2020-11-20 05:22:57,499 INFO: 第14次 查询...
113 | 2020-11-20 05:23:02,503 INFO: 第15次 查询...
114 | 2020-11-20 05:23:07,506 INFO: 第16次 查询...
115 | 2020-11-20 05:23:12,509 INFO: 第17次 查询...
116 | 2020-11-20 05:23:17,515 INFO: 第18次 查询...
117 | 2020-11-20 05:23:22,520 INFO: 第19次 查询...
118 | 2020-11-20 05:23:27,522 INFO: 校验是否还在登录...
119 | 2020-11-20 05:23:27,684 INFO: 第[1]次请重新获取cookie...
120 | 2020-11-20 05:23:32,848 INFO: 第[2]次请重新获取cookie...
121 | 2020-11-20 05:23:37,853 INFO: 第20次 查询...
122 | 2020-11-20 05:23:42,858 INFO: 第21次 查询...
123 | 2020-11-20 05:23:47,863 INFO: 第22次 查询...
124 | 2020-11-20 05:26:41,576 INFO: 登录成功!
125 | 2020-11-20 05:26:41,722 INFO: 登录账号名称: 金诺1099
126 | 2020-11-20 05:26:41,723 INFO: 第1次 查询...
127 | 2020-11-20 05:26:46,728 INFO: 第2次 查询...
128 | 2020-11-20 05:26:51,733 INFO: 第3次 查询...
129 | 2020-11-20 05:26:56,736 INFO: 第4次 查询...
130 | 2020-11-20 05:38:39,667 INFO: 登录成功!
131 | 2020-11-20 05:38:39,849 INFO: 登录账号名称: 金诺1099
132 | 2020-11-20 05:38:39,850 INFO: 第1次 查询...
133 | 2020-11-20 05:39:40,265 INFO: 第2次 查询...
134 | 2020-11-20 05:41:41,923 INFO: 登录成功!
135 | 2020-11-20 05:41:42,179 INFO: 登录账号名称: 金诺1099
136 | 2020-11-20 05:41:42,180 INFO: 第1次 查询...
137 | 2020-11-20 05:41:42,537 INFO: [10022306971495]商品无货.
138 | 2020-11-20 05:41:47,543 INFO: 第2次 查询...
139 | 2020-11-20 05:41:47,694 INFO: [10022306971495]商品无货.
140 | 2020-11-20 05:47:10,269 INFO: 登录成功!
141 | 2020-11-20 05:47:10,401 INFO: 登录账号名称: 金诺1099
142 | 2020-11-20 05:47:10,401 INFO: 第1次 查询...
143 | 2020-11-20 05:47:10,529 INFO: [10023884082830]商品无货.
144 | 2020-11-20 05:47:15,535 INFO: 第2次 查询...
145 | 2020-11-20 05:47:15,670 INFO: [10023884082830]商品无货.
146 | 2020-11-20 05:47:20,676 INFO: 第3次 查询...
147 | 2020-11-20 05:47:20,812 INFO: [10023884082830]商品无货.
148 | 2020-11-20 05:51:10,977 INFO: 登录成功!
149 | 2020-11-20 05:51:11,128 INFO: 登录账号名称: 金诺1099
150 | 2020-11-20 05:51:11,129 INFO: 第1次 查询...
151 | 2020-11-20 05:51:11,264 INFO: [868883]商品无货.
152 | 2020-11-20 05:51:16,270 INFO: 第2次 查询...
153 | 2020-11-20 05:51:16,404 INFO: [868883]商品无货.
154 | 2020-11-20 05:51:21,409 INFO: 第3次 查询...
155 | 2020-11-20 05:51:21,731 INFO: [868883]商品无货.
156 | 2020-11-20 05:51:26,736 INFO: 第4次 查询...
157 | 2020-11-20 05:51:26,867 INFO: [868883]商品无货.
158 | 2020-11-20 05:51:31,873 INFO: 第5次 查询...
159 | 2020-11-20 05:51:32,005 INFO: [868883]商品无货.
160 | 2020-11-20 05:55:37,205 INFO: 登录成功!
161 | 2020-11-20 05:55:37,469 INFO: 登录账号名称: 金诺1099
162 | 2020-11-20 05:55:37,470 INFO: 第1次 查询...
163 | 2020-11-21 02:01:07,710 INFO: 登录成功!
164 | 2020-11-21 02:01:07,856 INFO: 登录账号名称: 金诺1099
165 | 2020-11-21 02:01:07,857 INFO: 第1次 查询...
166 | 2020-11-21 02:01:08,016 INFO: [868883]商品无货.
167 | 2020-11-21 02:01:13,021 INFO: 第2次 查询...
168 | 2020-11-21 02:01:13,154 INFO: [868883]商品无货.
169 | 2020-11-21 02:40:48,233 INFO: 登录成功!
170 | 2020-11-21 02:40:48,379 INFO: 登录账号名称: 金诺1099
171 | 2020-11-21 02:40:48,379 INFO: 第1次 查询...
172 | 2020-11-21 02:40:48,534 INFO: [868883]商品无货.
173 | 2020-11-21 02:40:53,538 INFO: 第2次 查询...
174 | 2020-11-21 02:40:53,672 INFO: [868883]商品无货.
175 | 2020-11-21 03:41:30,295 INFO: 登录成功!
176 | 2020-11-21 03:41:30,536 INFO: 登录账号名称: 金诺1099
177 | 2020-11-21 03:41:30,536 INFO: 第1次 查询...
178 | 2020-11-21 03:41:31,355 INFO: [868883]商品有货啦! 马上下单...
179 | 2020-11-21 03:41:31,356 INFO: 第[1/5]次尝试提交订单
180 | 2020-11-21 03:41:33,213 INFO: 868883 已成功加入购物车
181 | 2020-11-21 03:41:33,636 INFO: 当前购物车信息: {}
182 | 2020-11-21 03:41:34,402 INFO: 下单信息: {'address': '湖北 黄石市 大冶市 还地桥镇 长岭村费家边湾', 'receiver': '程先生 156****9627', 'total_price': '19.80', 'items': []}
183 | 2020-11-21 03:41:34,583 INFO: 订单提交成功! 订单号: 138742874826
184 | 2020-11-21 03:43:32,352 INFO: 登录成功!
185 | 2020-11-21 03:43:32,588 INFO: 登录账号名称: 金诺1099
186 | 2020-11-21 03:43:32,589 INFO: 第1次 查询...
187 | 2020-11-21 03:43:46,484 INFO: 第2次 查询...
188 | 2020-11-21 03:43:57,430 INFO: 第3次 查询...
189 | 2020-11-21 03:43:57,856 INFO: [868883]商品有货啦! 马上下单...
190 | 2020-11-21 03:43:57,856 INFO: 第[1/5]次尝试提交订单
191 | 2020-11-21 03:43:58,957 INFO: 868883 已成功加入购物车
192 | 2020-11-21 03:43:59,641 INFO: 当前购物车信息: {}
193 | 2020-11-21 03:44:00,870 INFO: 下单信息: {'address': '湖北 黄石市 大冶市 还地桥镇 长岭村费家边湾', 'receiver': '程先生 156****9627', 'total_price': '19.80', 'items': []}
194 | 2020-11-21 03:44:01,069 INFO: 订单提交成功! 订单号: 132966892561
195 | 2020-11-21 03:46:06,509 INFO: 登录成功!
196 | 2020-11-21 03:46:06,657 INFO: 登录账号名称: 金诺1099
197 | 2020-11-21 03:46:06,658 INFO: 第1次 查询...
198 | 2020-11-21 03:46:51,683 INFO: 登录成功!
199 | 2020-11-21 03:46:51,819 INFO: 登录账号名称: 金诺1099
200 | 2020-11-21 03:46:51,819 INFO: 第1次 查询...
201 | 2020-11-21 03:47:37,831 INFO: 登录成功!
202 | 2020-11-21 03:47:37,974 INFO: 登录账号名称: 金诺1099
203 | 2020-11-21 03:47:37,975 INFO: 第1次 查询...
204 | 2020-11-21 03:47:48,104 INFO: 第2次 查询...
205 | 2020-11-21 03:48:20,802 INFO: 登录成功!
206 | 2020-11-21 03:48:20,934 INFO: 登录账号名称: 金诺1099
207 | 2020-11-21 03:48:20,935 INFO: 第1次 查询...
208 | 2020-11-22 03:48:38,435 INFO: 第[1]次请重新获取cookie...
209 | 2020-11-22 03:48:43,691 INFO: 第[2]次请重新获取cookie...
210 | 2020-11-22 03:48:48,856 INFO: 登录账号名称: 金诺1099
211 | 2020-11-22 03:48:48,857 INFO: 第1次 查询...
212 | 2020-11-22 04:29:01,998 INFO: 第[1]次请重新获取cookie...
213 | 2020-11-22 04:29:07,165 INFO: 第[2]次请重新获取cookie...
214 | 2020-11-22 04:29:12,486 INFO: 登录账号名称: 金诺1099
215 | 2020-11-22 04:29:12,487 INFO: 第1次 查询...
216 | 2020-11-22 04:29:13,339 INFO: [4708316]商品有货啦! 马上下单...
217 | 2020-11-22 04:29:13,340 INFO: 第[1/5]次尝试提交订单
218 | 2020-11-22 04:29:25,177 INFO: 第2次 查询...
219 | 2020-11-22 04:29:25,956 INFO: [4708316]商品有货啦! 马上下单...
220 | 2020-11-22 04:29:25,956 INFO: 第[1/5]次尝试提交订单
221 | 2020-11-22 04:29:36,924 INFO: 第3次 查询...
222 | 2020-11-22 04:29:37,391 INFO: [4708316]商品有货啦! 马上下单...
223 | 2020-11-22 04:29:37,391 INFO: 第[1/5]次尝试提交订单
224 | 2020-11-22 04:29:47,901 INFO: 第4次 查询...
225 | 2020-11-22 04:29:48,344 INFO: [4708316]商品有货啦! 马上下单...
226 | 2020-11-22 04:29:48,345 INFO: 第[1/5]次尝试提交订单
227 | 2020-11-22 04:34:04,499 INFO: 登录成功!
228 | 2020-11-22 04:34:04,648 INFO: 登录账号名称: 金诺1099
229 | 2020-11-22 04:34:04,648 INFO: 第1次 查询...
230 | 2020-11-22 04:34:05,082 INFO: [4708316]商品有货啦! 马上下单...
231 | 2020-11-22 04:34:05,083 INFO: 第[1/5]次尝试提交订单
232 | 2020-11-22 04:34:06,046 INFO: 4708316 已成功加入购物车
233 | 2020-11-22 04:34:06,493 INFO: 当前购物车信息: {}
234 | 2020-11-22 04:34:07,198 INFO: 下单信息: {'address': '湖北 黄石市 大冶市 还地桥镇 长岭村费家边湾', 'receiver': '程先生 156****9627', 'total_price': '19.80', 'items': []}
235 | 2020-11-22 04:34:07,388 INFO: 订单提交成功! 订单号: 138769320323
236 |
--------------------------------------------------------------------------------
/Console Version/my_test.py:
--------------------------------------------------------------------------------
1 | import time
2 | import re
3 | import requests
4 | import socket,getpass
5 | from JDAutoBuyTool import sendError
6 | import JDAutoBuyTool as jd
7 |
8 | # print('time.asctime() = {}'.format(time.asctime()))
9 |
10 | # print('time.time() = {}'.format(time.time()))
11 | # print('time.time() = {}'.format(time.time()))
12 | # print('username = {}, hostname = {}'.format(getpass.getuser(),socket.gethostname()))
13 |
14 | infilename = './Please fill out this document.txt'
15 | fp = open(infilename, 'r', encoding='utf-8')
16 | cont = fp.read()
17 | pattern = re.compile("'(.*)'")
18 | contRe = pattern.findall(cont)
19 | # print('contRe = ',contRe)
20 | contRe = contRe[2:]
21 | fp.close()
22 | url =contRe
23 | # print(url)
24 | for i in url:
25 | skuId = i.split('skuIds=')[1].split('%2C')[2]
26 | skuIdUrl = 'https://item.jd.com/' + skuId + '.html'
27 | print('skuIdUrl = {}'.format(skuIdUrl))
28 |
29 | mysession = requests.session()
30 | mysession.headers = {
31 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
32 | "Accept": "*/*",
33 | "Connection": "keep-alive"
34 | }
35 |
36 | response = mysession.get(i)
37 | # print('response = ',response.text) #
38 | j = response.text.find(str(skuId))
39 | # print(response.text.find(str(skuId)))
40 | # print(len(str(skuId)))
41 | # print(response.text[j:j+len(str(skuId))])
42 | tmp = response.text.split(str(skuId))[1]
43 | m = tmp.find('{')
44 | n = tmp.find('}')
45 | tmp = tmp[m:n+1]
46 | print(m,n)
47 | print(tmp)
48 |
49 | dict1 = {
50 | 'a' : 12,
51 | 'b' : 23
52 | }
53 | print(dict1)
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Console Version/requirements.txt:
--------------------------------------------------------------------------------
1 | requests==2.22.0
2 | beautifulsoup4==4.8.2
3 |
--------------------------------------------------------------------------------
/Console Version/test.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''
4 | 【简介】
5 | PyQt5中QButton例子
6 | '''
7 |
8 | import sys
9 | from PyQt5.QtCore import *
10 | from PyQt5.QtGui import *
11 | from PyQt5.QtWidgets import *
12 |
13 | class Form(QDialog):
14 | def __init__(self, parent=None):
15 | super(Form, self).__init__(parent)
16 | layout = QVBoxLayout() #设置垂直布局
17 |
18 | self.btn1 = QPushButton("Button1")
19 | # setChenkable():设置按钮是否已经被选中,true表示按钮将被保持已点击和释放状态
20 | self.btn1.setCheckable(True)
21 | # toggle():在按钮之间进行切换
22 | self.btn1.toggle()
23 | # 通过lambda方式来传递额外的参数btn1,将clicked信号发送给槽函数whichbtn()
24 | self.btn1.clicked.connect(lambda:self.whichbtn(self.btn1) )
25 | self.btn1.clicked.connect(self.btnstate)
26 | layout.addWidget(self.btn1)
27 |
28 | self.btn2 = QPushButton('image')
29 | self.btn2.setIcon(QIcon(QPixmap("./images/python.png")))
30 | self.btn2.clicked.connect(lambda:self.whichbtn(self.btn2) )
31 | layout.addWidget(self.btn2)
32 | self.setLayout(layout)
33 |
34 | self.btn3 = QPushButton("Disabled")
35 | # setEnabled():设置按钮是否可用,false时按钮变成不可用状态,点击它不会发送信号
36 | self.btn3.setEnabled(False)
37 | layout.addWidget(self.btn3)
38 |
39 | self.btn4= QPushButton("&Download")
40 | self.btn4.setDefault(True) #设置按钮的默认状态
41 | self.btn4.clicked.connect(lambda:self.whichbtn(self.btn4))
42 | layout.addWidget(self.btn4)
43 | self.setWindowTitle("Button demo")
44 |
45 | def btnstate(self):
46 | if self.btn1.isChecked(): #返回按钮的状态
47 | print("button pressed" )
48 |
49 | else:
50 | print("button released" )
51 |
52 | def whichbtn(self,btn):
53 | print("clicked button is " + btn.text() )
54 |
55 | if __name__ == '__main__':
56 | app = QApplication(sys.argv)
57 | btnDemo = Form()
58 | btnDemo.show()
59 | sys.exit(app.exec_())
--------------------------------------------------------------------------------
/Console Version/test2.py:
--------------------------------------------------------------------------------
1 | PI = 3.1415926
2 | def main1():
3 | print('PI = ',PI)
4 |
5 |
6 | if __name__ == "__main__":
7 | main1()
--------------------------------------------------------------------------------
/GUI Version/autobuy.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'qsswindow.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.14.1
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 | from PyQt5.QtWidgets import QApplication
11 | from PyQt5.QtCore import QTimer
12 |
13 | import sys
14 |
15 | import argparse
16 | import os
17 | import pickle
18 | import random
19 | import time
20 | import json
21 | import requests
22 | import re
23 | import logging
24 | import logging.handlers
25 | from bs4 import BeautifulSoup
26 | import smtplib
27 | from email.mime.text import MIMEText
28 | from email.header import Header
29 |
30 | class Ui_QSSWindow(object):
31 | def setupUi(self, QSSWindow):
32 | QSSWindow.setObjectName("QSSWindow")
33 | QSSWindow.resize(950, 450)
34 | self.centralwidget = QtWidgets.QWidget(QSSWindow)
35 | self.centralwidget.setObjectName("centralwidget")
36 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralwidget)
37 | self.verticalLayout_3.setObjectName("verticalLayout_3")
38 | self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
39 | self.tabWidget.setObjectName("tabWidget")
40 | self.tab = QtWidgets.QWidget()
41 | self.tab.setObjectName("tab")
42 |
43 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab)
44 | self.verticalLayout_2.setObjectName("verticalLayout_2")
45 | self.groupBox = QtWidgets.QGroupBox(self.tab)
46 | self.groupBox.setObjectName("groupBox")
47 | self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox)
48 | self.verticalLayout.setObjectName("verticalLayout")
49 | self.goods = QtWidgets.QHBoxLayout()
50 | self.goods.setObjectName("goods")
51 | self.labelGoods = QtWidgets.QLabel(self.groupBox)
52 | self.labelGoods.setObjectName("labelGoods")
53 | self.goods.addWidget(self.labelGoods)
54 | self.inputGoods = QtWidgets.QLineEdit(self.groupBox)
55 | self.inputGoods.setObjectName("inputGoods")
56 | self.goods.addWidget(self.inputGoods)
57 | self.verticalLayout.addLayout(self.goods)
58 | self.area = QtWidgets.QHBoxLayout()
59 | self.area.setObjectName("area")
60 | self.labelArea = QtWidgets.QLabel(self.groupBox)
61 | self.labelArea.setObjectName("labelArea")
62 | self.area.addWidget(self.labelArea)
63 | self.inputArea = QtWidgets.QLineEdit(self.groupBox)
64 | self.inputArea.setObjectName("inputArea")
65 | self.area.addWidget(self.inputArea)
66 |
67 | self.labelMail = QtWidgets.QLabel(self.groupBox)
68 | self.labelMail.setObjectName("labelMail")
69 | self.area.addWidget(self.labelMail)
70 | self.inputMail = QtWidgets.QLineEdit(self.groupBox)
71 | self.inputMail.setObjectName("inputMail")
72 | self.area.addWidget(self.inputMail)
73 |
74 | self.labelNum = QtWidgets.QLabel(self.groupBox)
75 | self.labelNum.setObjectName("labelNum")
76 | self.area.addWidget(self.labelNum)
77 | self.comboBox = QtWidgets.QComboBox(self.groupBox)
78 | self.comboBox.setObjectName("comboBox")
79 | self.area.addWidget(self.comboBox)
80 |
81 | self.checkBox = QtWidgets.QCheckBox(self.groupBox)
82 | self.checkBox.setObjectName("checkBox")
83 | self.area.addWidget(self.checkBox)
84 |
85 | self.verticalLayout.addLayout(self.area)
86 | self.speedLayout = QtWidgets.QHBoxLayout()
87 | self.speedLayout.setObjectName("speedLayout")
88 | self.horizontalSlider = QtWidgets.QSlider(self.groupBox)
89 | self.horizontalSlider.setMaximum(100)
90 | self.horizontalSlider.setProperty("value", 50)
91 | self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
92 | self.horizontalSlider.setTickInterval(0)
93 | self.horizontalSlider.setObjectName("horizontalSlider")
94 | self.speedLayout.addWidget(self.horizontalSlider)
95 | self.progressBar = QtWidgets.QProgressBar(self.groupBox)
96 | self.progressBar.setProperty("value", 24)
97 | self.progressBar.setObjectName("progressBar")
98 | self.speedLayout.addWidget(self.progressBar)
99 |
100 | self.verticalLayout.addLayout(self.speedLayout)
101 | self.textEdit = QtWidgets.QTextEdit(self.groupBox)
102 | self.textEdit.setObjectName("textEdit")
103 | self.verticalLayout.addWidget(self.textEdit)
104 | self.buttonLayout = QtWidgets.QHBoxLayout()
105 | self.buttonLayout.setObjectName("buttonLayout")
106 | self.loginBtn = QtWidgets.QPushButton(self.groupBox)
107 | self.loginBtn.setStyleSheet("")
108 | self.loginBtn.setObjectName("loginBtn")
109 | self.buttonLayout.addWidget(self.loginBtn)
110 | self.startBtn = QtWidgets.QPushButton(self.groupBox)
111 | self.startBtn.setStyleSheet("")
112 | self.startBtn.setObjectName("startBtn")
113 | self.buttonLayout.addWidget(self.startBtn)
114 | self.stopBtn = QtWidgets.QPushButton(self.groupBox)
115 | self.stopBtn.setStyleSheet("")
116 | self.stopBtn.setObjectName("stopBtn")
117 | self.buttonLayout.addWidget(self.stopBtn)
118 | self.verticalLayout.addLayout(self.buttonLayout)
119 | self.verticalLayout_2.addWidget(self.groupBox)
120 | self.tabWidget.addTab(self.tab, "")
121 | self.tab_1 = QtWidgets.QWidget()
122 | self.tab_1.setObjectName("tab_1")
123 |
124 | self.labelAboutMe = QtWidgets.QLabel(self.tab_1)
125 | # self.labelAboutMe.setGeometry(QtCore.QRect(50, 30, 280, 180))
126 | self.labelAboutMe.setObjectName("labelAboutMe")
127 |
128 | self.tabWidget.addTab(self.tab_1, "")
129 | self.verticalLayout_3.addWidget(self.tabWidget)
130 | QSSWindow.setCentralWidget(self.centralwidget)
131 | self.statusbar = QtWidgets.QStatusBar(QSSWindow)
132 | self.statusbar.setObjectName("statusbar")
133 | QSSWindow.setStatusBar(self.statusbar)
134 | self.menubar = QtWidgets.QMenuBar(QSSWindow)
135 | self.menubar.setGeometry(QtCore.QRect(0, 0, 680, 25))
136 | self.menubar.setObjectName("menubar")
137 | self.file = QtWidgets.QMenu(self.menubar)
138 | self.file.setObjectName("file")
139 | self.edit = QtWidgets.QMenu(self.menubar)
140 | self.edit.setObjectName("edit")
141 | QSSWindow.setMenuBar(self.menubar)
142 | self.file.addSeparator()
143 | self.menubar.addAction(self.file.menuAction())
144 | self.menubar.addAction(self.edit.menuAction())
145 |
146 | self.retranslateUi(QSSWindow)
147 | self.tabWidget.setCurrentIndex(5)
148 | QtCore.QMetaObject.connectSlotsByName(QSSWindow)
149 |
150 |
151 |
152 |
153 |
154 | def retranslateUi(self, QSSWindow):
155 | _translate = QtCore.QCoreApplication.translate
156 | QSSWindow.setWindowTitle(_translate("QSSWindow", "MainWindow"))
157 | self.tabWidget.setToolTip(_translate("QSSWindow", "
"))
158 | self.tabWidget.setWhatsThis(_translate("QSSWindow", "
"))
159 | self.groupBox.setTitle(_translate("QSSWindow", "一定能尽快战胜疫情, 中国加油!"))
160 | self.labelGoods.setText(_translate("QSSWindow", "请输入商品ID(以逗号间隔):"))
161 | self.labelArea.setText(_translate("QSSWindow", "请输入收件地区编码:"))
162 | self.labelMail.setText(_translate("QSSWindow", "接受讯息邮箱:"))
163 | self.labelNum.setText(_translate("QSSWindow", "购买数量:"))
164 | self.loginBtn.setText(_translate("QSSWindow", "扫码登录"))
165 | self.startBtn.setText(_translate("QSSWindow", "开始监控(可自动登录)"))
166 | self.stopBtn.setText(_translate("QSSWindow", "停止监控"))
167 | self.checkBox.setText(_translate("QSSWindow", "是否自动忽略下架商品"))
168 |
169 |
170 | self.labelAboutMe.setText(_translate("QSSWindow", '使用指南
请点击这里跳转 战疫情, 加油!
欢迎在GitHub上加星. 谢谢!
Tips: 登录一次之后本地会保存登录信息, 重启软件之后仍然可以记住账号登录信息
只需点击"开始监控"就可以自动登录, 不必重复扫码哦
'))
171 | self.labelAboutMe.setOpenExternalLinks(True)
172 |
173 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("QSSWindow", "Console"))
174 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_1), _translate("QSSWindow", "指南"))
175 |
176 | self.file.setTitle(_translate("QSSWindow", "文件"))
177 | self.edit.setTitle(_translate("QSSWindow", "编辑"))
178 |
179 |
180 |
181 | class Autobuy(QtWidgets.QMainWindow, Ui_QSSWindow):
182 | def __init__(self):
183 | super().__init__()
184 | self.sess = requests.Session()
185 | self.sess.headers = {
186 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36",
187 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
188 | "Referer": "https://order.jd.com/center/list.action",
189 | "Connection": "keep-alive"
190 | }
191 |
192 | self.headers = {
193 | "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",
194 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
195 | "Referer": "https://cart.jd.com/cart.action",
196 | "Connection": "keep-alive"
197 | }
198 |
199 | self.speed = 5000
200 | self.isMonitorSoldout = True
201 | # self.isLogin = False
202 | self.cookiesString = ''
203 | self.cookies = {}
204 | self.skuidString = ''
205 | self.skuid = []
206 | self.cont = 1
207 | self.timer = QTimer(self)
208 | self.logger = logging.getLogger()
209 | self.loadQSS()
210 | self.setupUi(self)
211 | self.connectSign()
212 | self.initData()
213 | self.show()
214 |
215 |
216 | def loadQSS(self):
217 | file = 'window.qss'
218 | with open(file, 'rt', encoding='utf8') as f:
219 | styleSheet = f.read()
220 | self.setStyleSheet(styleSheet)
221 | f.close()
222 |
223 | def setLogger(self, logFileName='jdAutoBuyGood.log'):
224 | self.logger.setLevel(logging.INFO)
225 | formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
226 |
227 | console_handler = logging.StreamHandler()
228 | console_handler.setFormatter(formatter)
229 | self.logger.addHandler(console_handler)
230 |
231 | file_handler = logging.handlers.RotatingFileHandler(
232 | logFileName, maxBytes=10485760, backupCount=5, encoding="utf-8")
233 | file_handler.setFormatter(formatter)
234 | self.logger.addHandler(file_handler)
235 |
236 | def initData(self):
237 | self.inputGoods.setText("65466451629,65437208345,7498169,7498165,1835968,7263128,7498167,17449572304,37934196731,100001086804,56657322838,56657322841,100005294853,1938795,15595191653,15595191654,45923412989,1835967,1336984,65466451629,7498169,7263128,4061438,65421329578,100005678825,100005294853,45923412989,62830056100,45006657879")
238 | self.inputArea.setText("16_1362_44319_51500")
239 | self.inputMail.setText("$$$$$$$@qq.com")
240 | self.comboBox.addItems(['1', '2', '3'])
241 | self.horizontalSlider.setValue(50)
242 | self.horizontalSlider.setMaximum(100)
243 | self.horizontalSlider.setMinimum(0)
244 | self.setProgressBar()
245 |
246 | self.setLogger()
247 |
248 | if len(self.cookiesString) != 0:
249 | manual_cookies = {}
250 | for item in self.cookiesString.split(';'):
251 | # 用=号分割.
252 | name, value = item.strip().split('=', 1)
253 | manual_cookies[name] = value
254 | self.cookies = requests.utils.cookiejar_from_dict(manual_cookies, cookiejar=None, overwrite=True)
255 | self.sess.cookies = self.cookies
256 |
257 | def connectSign(self):
258 | self.horizontalSlider.valueChanged.connect(self.setProgressBar)
259 | self.horizontalSlider.valueChanged[int].connect(self.slvaluechange)
260 |
261 | self.loginBtn.clicked.connect(self.loginByQR)
262 | self.startBtn.clicked.connect(self.monitorConnect)
263 | self.stopBtn.clicked.connect(self.stopConnect)
264 |
265 | def stopConnect(self):
266 | self.updateStateText("已停止监控.")
267 | self.timer.stop()
268 |
269 | def stopNow(self):
270 | self.updateStateText("已停止监控.")
271 | self.timer.stop()
272 |
273 | def slvaluechange(self, val):
274 | # self.updateStateText("设置抢购速度: %d" % val)
275 | if val > 85:
276 | self.speed = 500
277 | elif val > 60:
278 | self.speed = 9000 - val * 100
279 | else:
280 | self.speed = 10000 - val * 100
281 |
282 | def setProgressBar(self):
283 | self.progressBar.setValue(self.horizontalSlider.value())
284 |
285 | def checkLogin(self):
286 | self.updateStateText('正在验证登录状态...')
287 | for flag in range(1, 3):
288 | try:
289 | targetURL = 'https://order.jd.com/center/list.action'
290 | payload = {
291 | 'rid': str(int(time.time() * 1000)),
292 | }
293 | resp = self.sess.get(url=targetURL, params=payload, allow_redirects=False)
294 | if resp.status_code == requests.codes.OK:
295 | self.updateStateText('登录成功!')
296 | return True
297 | else:
298 | self.updateStateText('第 %s 次再尝试验证cookie...' % flag)
299 | self.updateStateText('正在尝试从历史讯息中恢复...')
300 | with open('cookie', 'rb') as f:
301 | cookies = requests.utils.cookiejar_from_dict(pickle.load(f))
302 | # print(cookies)
303 | self.sess.cookies = cookies
304 | continue
305 | except Exception as e:
306 | self.updateStateText(str(e))
307 | self.updateStateText('第 %s 次再尝试验证cookie...' % flag)
308 | continue
309 | self.updateStateText('请登录!')
310 | return False
311 |
312 | def loginByQR(self):
313 | # jd login by QR code
314 | try:
315 | self.updateStateText('请您打开京东手机客户端或微信扫一扫, 准备扫码登录')
316 |
317 | urls = (
318 | 'https://passport.jd.com/new/login.aspx',
319 | 'https://qr.m.jd.com/show',
320 | 'https://qr.m.jd.com/check',
321 | 'https://passport.jd.com/uc/qrCodeTicketValidation'
322 | )
323 | # step 1: open login page
324 | response = self.sess.get(
325 | urls[0],
326 | headers=self.headers
327 | )
328 | if response.status_code != requests.codes.OK:
329 | self.updateStateText(f'获取登录页失败: {response.status_code}')
330 | # self.isLogin = False
331 | return False
332 | # update cookies
333 | self.cookies.update(response.cookies)
334 | self.sess.cookies = response.cookies
335 |
336 | # step 2: get QR image
337 | response = self.sess.get(
338 | urls[1],
339 | headers=self.headers,
340 | cookies=self.cookies,
341 | params={
342 | 'appid': 133,
343 | 'size': 147,
344 | 't': int(time.time() * 1000),
345 | }
346 | )
347 | if response.status_code != requests.codes.OK:
348 | self.updateStateText(f'获取二维码失败: {response.status_code}')
349 | # self.isLogin = False
350 | return False
351 |
352 | # update cookies
353 | self.cookies.update(response.cookies)
354 | self.sess.cookies = response.cookies
355 |
356 | # save QR code
357 | image_file = 'qr.png'
358 | with open(image_file, 'wb') as f:
359 | for chunk in response.iter_content(chunk_size=1024):
360 | f.write(chunk)
361 |
362 | # scan QR code with phone
363 | if os.name == "nt":
364 | # for windows
365 | os.system('start ' + image_file)
366 | else:
367 | if os.uname()[0] == "Linux":
368 | # for linux platform
369 | os.system("eog " + image_file)
370 | else:
371 | # for Mac platform
372 | os.system("open " + image_file)
373 |
374 | # step 3: check scan result
375 | self.headers['Host'] = 'qr.m.jd.com'
376 | self.headers['Referer'] = 'https://passport.jd.com/new/login.aspx'
377 |
378 | # check if QR code scanned
379 | qr_ticket = None
380 | retry_times = 1000 # 尝试1000次
381 | while retry_times:
382 | retry_times -= 1
383 | response = self.sess.get(
384 | urls[2],
385 | headers=self.headers,
386 | cookies=self.cookies,
387 | params={
388 | 'callback': 'jQuery%d' % random.randint(1000000, 9999999),
389 | 'appid': 133,
390 | 'token': self.cookies['wlfstk_smdl'],
391 | '_': int(time.time() * 1000)
392 | }
393 | )
394 | if response.status_code != requests.codes.OK:
395 | continue
396 | rs = json.loads(re.search(r'{.*?}', response.text, re.S).group())
397 | if rs['code'] == 200:
398 | self.updateStateText(f"{rs['ticket']}(Response Code: {rs['code']})")
399 | qr_ticket = rs['ticket']
400 | break
401 | else:
402 | self.updateStateText(f"{rs['msg']}(Response Code: {rs['code']})")
403 | time.sleep(2)
404 |
405 | if not qr_ticket:
406 | self.updateStateText("ERROR: 二维码登录失败.")
407 | # self.isLogin = False
408 | return False
409 |
410 | # step 4: validate scan result
411 | self.headers['Host'] = 'passport.jd.com'
412 | self.headers['Referer'] = 'https://passport.jd.com/new/login.aspx'
413 | response = requests.get(
414 | urls[3],
415 | headers=self.headers,
416 | cookies=self.cookies,
417 | params={'t': qr_ticket},
418 | )
419 | if response.status_code != requests.codes.OK:
420 | self.updateStateText(f"二维码登录校验失败: {response.status_code}")
421 | # self.isLogin = False
422 | return False
423 |
424 | # 京东有时会认为当前登录有危险, 需要手动验证
425 | # url: https://safe.jd.com/dangerousVerify/index.action?username=...
426 | res = json.loads(response.text)
427 | if not response.headers.get('p3p'):
428 | if 'url' in res:
429 | self.updateStateText(f"请进行手动安全验证: {res['url']}")
430 | # self.isLogin = False
431 | return False
432 | else:
433 | self.updateStateText('登录失败, ERROR message: ' + res)
434 | # self.isLogin = False
435 | return False
436 |
437 | # login succeed
438 | self.headers['P3P'] = response.headers.get('P3P')
439 | self.cookies.update(response.cookies)
440 | self.sess.cookies = response.cookies
441 |
442 |
443 | # save cookie
444 | with open('cookie', 'wb') as f:
445 | pickle.dump(self.cookies, f)
446 |
447 | self.updateStateText("登录成功!")
448 | # self.isLogin = True
449 | self.getUsername()
450 | return True
451 |
452 | except Exception as e:
453 | # self.isLogin = False
454 | self.updateStateText('ERROR message: ' + str(e))
455 | raise
456 |
457 | def getUsername(self):
458 | userName_Url = 'https://passport.jd.com/new/helloService.ashx?callback=jQuery339448&_=' + str(
459 | int(time.time() * 1000))
460 |
461 | resp = self.sess.get(url=userName_Url, allow_redirects=True)
462 | resultText = resp.text
463 | resultText = resultText.replace('jQuery339448(', '')
464 | resultText = resultText.replace(')', '')
465 | usernameJson = json.loads(resultText)
466 | self.updateStateText('账号名称: ' + usernameJson['nick'])
467 |
468 | def checkStock(self):
469 | url = 'https://c0.3.cn/stocks'
470 |
471 | callback = 'jQuery' + str(random.randint(1000000, 9999999))
472 |
473 | headers = {
474 | "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",
475 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
476 | "Referer": "https://cart.jd.com/cart.action",
477 | "Connection": "keep-alive",
478 | }
479 |
480 | payload = {
481 | 'type': 'getstocks',
482 | 'skuIds': self.skuidString,
483 | 'area': self.areaID,
484 | 'callback': callback,
485 | '_': int(time.time() * 1000),
486 | }
487 | resp = self.sess.get(url=url, params=payload, headers=headers)
488 | respText = resp.text.replace(callback + '(', '').replace(')', '')
489 | respJson = json.loads(respText)
490 | inStockSkuid = []
491 | nohasSkuid = []
492 | abnormalSkuid = []
493 |
494 | soldOut = 0
495 | alloca = 0
496 | for i in self.skuid:
497 | try:
498 | if respJson[i]['StockStateName'] == '无货':
499 | nohasSkuid.append(i)
500 | soldOut += 1
501 | elif respJson[i]['StockStateName'] == '可配货':
502 | nohasSkuid.append(i)
503 | alloca += 1
504 | else:
505 | inStockSkuid.append(i)
506 |
507 | except Exception as e:
508 | abnormalSkuid.append(i)
509 |
510 | if soldOut != 0:
511 | self.updateStateText('监控的 %d 个商品无货.' % soldOut)
512 | if alloca != 0:
513 | self.updateStateText('监控的 %d 个商品所在地区暂无货, 未来可能配货.' % alloca)
514 | if len(abnormalSkuid) > 0:
515 | self.updateStateText('WARNING: %s 编号商品查询异常.' % ','.join(abnormalSkuid))
516 | return inStockSkuid
517 |
518 | def isSoldOut(self, sku_id):
519 | headers = {
520 | "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",
521 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
522 | "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
523 | "Connection": "keep-alive",
524 | 'Host': 'item.jd.com',
525 | }
526 | url = 'https://item.jd.com/{}.html'.format(sku_id)
527 | page = requests.get(url=url, headers=headers)
528 | return '该商品已下柜' not in page.text
529 |
530 | def selectAll(self):
531 | url = "https://cart.jd.com/selectAllItem.action"
532 | data = {
533 | 't': 0,
534 | 'outSkus': '',
535 | 'random': random.random()
536 | }
537 | resp = self.sess.post(url, data=data)
538 | if resp.status_code != requests.codes.OK:
539 | self.updateStateText('全选购物车商品出错! status_code: %u, URL: %s' % (resp.status_code, resp.url))
540 | return False
541 | self.updateStateText('全选购物车商品成功.')
542 | return True
543 |
544 | def cart_detail(self, isOutput=False):
545 | url = 'https://cart.jd.com/cart.action'
546 | resp = self.sess.get(url, headers=self.headers)
547 | soup = BeautifulSoup(resp.text, "html.parser")
548 |
549 | cartDetail = dict()
550 | for item in soup.find_all(class_='item-item'):
551 | sku_id = item['skuid'] # 商品id
552 | try:
553 | # 例如: ['increment', '8888', '100001071956', '1', '13', '0', '50067652554']
554 | # ['increment', '8888', '100002404322', '2', '1', '0']
555 | item_attr_list = item.find(class_='increment')['id'].split('_')
556 | p_type = item_attr_list[4]
557 | promo_id = target_id = item_attr_list[-1] if len(item_attr_list) == 7 else 0
558 |
559 | def get_tag_value(tag, key='', index=0):
560 | if key:
561 | value = tag[index].get(key)
562 | else:
563 | value = tag[index].text
564 | return value.strip(' \t\r\n')
565 |
566 | cartDetail[sku_id] = {
567 | 'name': get_tag_value(item.select('div.p-name a')), # 商品名称
568 | 'verder_id': item['venderid'], # 商家id
569 | 'count': int(item['num']), # 数量
570 | 'unit_price': get_tag_value(item.select('div.p-price strong'))[1:], # 单价
571 | 'total_price': get_tag_value(item.select('div.p-sum strong'))[1:], # 总价
572 | 'is_selected': 'item-selected' in item['class'], # 商品是否被勾选
573 | 'p_type': p_type,
574 | 'target_id': target_id,
575 | 'promo_id': promo_id
576 | }
577 | except Exception as e:
578 | self.updateStateText("ERROR: 商品%s在购物车中的信息无法解析, 报错信息: %s, 该商品自动忽略.", sku_id, e)
579 |
580 | if isOutput == True:
581 | self.updateStateText('当前购物车信息: %s.' % cartDetail)
582 | return cartDetail
583 |
584 | def addItemToCart(self, sku_id):
585 | url = 'https://cart.jd.com/gate.action'
586 | addNum = self.comboBox.currentIndex() + 1
587 | payload = {
588 | 'pid': sku_id,
589 | 'pcount': addNum,
590 | 'ptype': 1
591 | }
592 | resp = self.sess.get(url=url, params=payload)
593 | if 'https://cart.jd.com/cart.action' in resp.url: # 套装商品加入购物车后直接跳转到购物车页面
594 | result = True
595 | else: # 普通商品成功加入购物车后会跳转到提示 "商品已成功加入购物车!" 页面
596 | soup = BeautifulSoup(resp.text, "html.parser")
597 | result = bool(soup.select('h3.ftx-02')) # [商品已成功加入购物车!
]
598 |
599 | if result:
600 | self.updateStateText('%s 编号商品已成功加入购物车, 数量: %d.' % (sku_id, addNum))
601 | else:
602 | self.updateStateText('ERROR: %s 编号商品添加到购物车失败.' % sku_id)
603 |
604 | def responseStatus(self, resp):
605 | if resp.status_code != requests.codes.OK:
606 | self.updateStateText('Status: %u, Url: %s' % (resp.status_code, resp.url))
607 | return False
608 | return True
609 |
610 | def getCheckoutPageDetail(self):
611 | url = 'http://trade.jd.com/shopping/order/getOrderInfo.action'
612 | # url = 'https://cart.jd.com/gotoOrder.action'
613 | payload = {
614 | 'rid': str(int(time.time() * 1000)),
615 | }
616 | headers = {
617 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36",
618 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
619 | "Referer": "https://cart.jd.com/cart.action",
620 | "Connection": "keep-alive",
621 | 'Host': 'trade.jd.com',
622 | }
623 | try:
624 | resp = self.sess.get(url=url, params=payload, headers=headers)
625 |
626 | if not self.responseStatus(resp):
627 | self.updateStateText('ERROR: 获取订单结算页信息失败.')
628 | return None
629 | soup = BeautifulSoup(resp.text, "html.parser")
630 |
631 | order_detail = {
632 | 'address': soup.find('span', id='sendAddr').text[5:],
633 | 'receiver': soup.find('span', id='sendMobile').text[4:],
634 | 'total_price': soup.find('span', id='sumPayPriceId').text[1:],
635 | 'items': []
636 | }
637 |
638 | self.updateStateText("下单信息: %s" % order_detail)
639 | return order_detail
640 | except requests.exceptions.RequestException as e:
641 | self.updateStateText('订单结算页面获取异常, ERROR message: %s.' % e)
642 | except Exception as e:
643 | self.updateStateText('下单页面数据解析异常, ERROR message: %s.' % e)
644 | return None
645 |
646 | def submit_order(self, risk_control, payment_pwd):
647 | url = 'https://trade.jd.com/shopping/order/submitOrder.action'
648 | # js function of submit order is included in https://trade.jd.com/shopping/misc/js/order.js?r=2018070403091
649 |
650 | # overseaPurchaseCookies:
651 | # vendorRemarks: []
652 | # submitOrderParam.sopNotPutInvoice: false
653 | # submitOrderParam.trackID: TestTrackId
654 | # submitOrderParam.ignorePriceChange: 0
655 | # submitOrderParam.btSupport: 0
656 | # riskControl:
657 | # submitOrderParam.isBestCoupon: 1
658 | # submitOrderParam.jxj: 1
659 | # submitOrderParam.trackId:
660 |
661 | data = {
662 | 'overseaPurchaseCookies': '',
663 | 'vendorRemarks': '[]',
664 | 'submitOrderParam.sopNotPutInvoice': 'false',
665 | 'submitOrderParam.trackID': 'TestTrackId',
666 | 'submitOrderParam.ignorePriceChange': '0',
667 | 'submitOrderParam.btSupport': '0',
668 | 'riskControl': risk_control,
669 | 'submitOrderParam.isBestCoupon': 1,
670 | 'submitOrderParam.jxj': 1,
671 | 'submitOrderParam.trackId': '9643cbd55bbbe103eef18a213e069eb0', # Todo: need to get trackId
672 | # 'submitOrderParam.eid': eid,
673 | # 'submitOrderParam.fp': fp,
674 | 'submitOrderParam.needCheck': 1,
675 | }
676 |
677 | def encrypt_payment_pwd(paymentPwd):
678 | return ''.join(['u3' + x for x in paymentPwd])
679 |
680 | if len(payment_pwd) > 0:
681 | data['submitOrderParam.payPassword'] = encrypt_payment_pwd(payment_pwd)
682 |
683 | headers = {
684 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36",
685 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
686 | "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
687 | "Connection": "keep-alive",
688 | 'Host': 'trade.jd.com',
689 | }
690 |
691 | try:
692 | resp = self.sess.post(url=url, data=data, headers=headers)
693 | resp_json = json.loads(resp.text)
694 |
695 | if resp_json.get('success'):
696 | self.updateStateText('订单提交成功! 订单号: %s' % resp_json.get('orderId'))
697 | return True
698 | else:
699 | message, result_code = resp_json.get('message'), resp_json.get('resultCode')
700 | if result_code == 0:
701 | # self._save_invoice()
702 | message = message + '(下单商品可能为第三方商品, 将切换为普通发票进行尝试)'
703 | elif result_code == 60077:
704 | message = message + '(可能是购物车为空或未勾选购物车中商品)'
705 | elif result_code == 60123:
706 | message = message + '(未配置支付密码)'
707 | self.updateStateText('订单提交失败, 错误码: %s, 返回信息: %s.' % (result_code, message))
708 | self.updateStateText(resp_json)
709 | return False
710 | except Exception as e:
711 | self.updateStateText("ERROR: " + str(e))
712 | return False
713 |
714 | def cancelSelectCartItem(self):
715 | url = "https://cart.jd.com/cancelAllItem.action"
716 | data = {
717 | 't': 0,
718 | 'outSkus': '',
719 | 'random': random.random()
720 | }
721 | resp = self.sess.post(url, data=data)
722 | if resp.status_code != requests.codes.OK:
723 | self.updateStateText('cancelSelectCartItem() function WARNING: %u, Url: %s' % (resp.status_code, resp.url))
724 | return False
725 | return True
726 |
727 | def buyGoods(self, sku_id):
728 | for i in range(1, 2):
729 | self.updateStateText('第 %d/%d 次尝试提交订单...' % (i, 2))
730 | self.cancelSelectCartItem()
731 | cart = self.cart_detail()
732 | if sku_id not in cart:
733 | self.addItemToCart(sku_id)
734 | self.cart_detail(True)
735 |
736 | risk_control = self.getCheckoutPageDetail()
737 | if risk_control != None:
738 | if self.submit_order(risk_control, ''):
739 | return True
740 | time.sleep(1)
741 | else:
742 | self.updateStateText('执行结束,提交订单失败.')
743 | return False
744 |
745 | def monitorConnect(self):
746 | if self.checkLogin() == False:
747 | return False
748 | self.skuidString = self.inputGoods.text()
749 | pattern = re.compile(",|,")
750 | self.skuid = pattern.split(self.skuidString)
751 |
752 | self.areaID = self.inputArea.text()
753 |
754 | self.timer.timeout.connect(self.monitorMain)
755 | self.updateStateText("当前轮询速度为 %f 秒/次." % (self.speed / 1000))
756 | if self.checkBox.isChecked():
757 | self.isMonitorSoldout = False
758 | self.updateStateText('当前模式将为您自动忽略并删除下架商品.')
759 | else:
760 | self.isMonitorSoldout = True
761 | self.updateStateText('当前模式将为您保持监控下架商品, 若其上架则立即抢购.')
762 | self.timer.start(self.speed) # 设置计时间隔并启动
763 | return True
764 |
765 | def sendMail(self, url, isOrder):
766 | sendTo = self.inputMail.text()
767 | if len(sendTo) == 0 or sendTo == '$$$$$$$@qq.com':
768 | return
769 |
770 | mailRe = re.compile('^\w{1,15}@\w{1,10}\.(com|cn|net)$')
771 | if not re.search(mailRe, sendTo):
772 | return
773 |
774 | sendFrom = '645064582@qq.com'
775 |
776 | smtp_server = 'smtp.qq.com'
777 | if isOrder:
778 | msg = MIMEText('您抢购的 ' + url + ' 商品已下单, 请在尽快付款.', 'plain', 'utf-8')
779 | else:
780 | msg = MIMEText('您抢购的 ' + url + ' 商品下单失败.', 'plain', 'utf-8')
781 |
782 | msg['From'] = Header(sendFrom)
783 | msg['To'] = Header(sendTo)
784 | msg['Subject'] = Header('京东商品自动购买程序提示讯息')
785 |
786 | server = smtplib.SMTP_SSL(host=smtp_server)
787 | server.connect(smtp_server, 465)
788 | server.login(sendFrom, 'nkrzicfjkzznbehi')
789 | server.sendmail(sendFrom, sendTo, msg.as_string())
790 | server.quit()
791 |
792 | def removeItem(self):
793 | url = "https://cart.jd.com/batchRemoveSkusFromCart.action"
794 | data = {
795 | 't': 0,
796 | 'null': '',
797 | 'outSkus': '',
798 | 'random': random.random(),
799 | 'locationId': '19-1607-4773-0'
800 | }
801 | headers = {
802 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.37",
803 | "Accept": "application/json, text/javascript, */*; q=0.01",
804 | "Referer": "https://cart.jd.com/cart.action",
805 | "Host": "cart.jd.com",
806 | "Content-Type": "application/x-www-form-urlencoded",
807 | "Accept-Encoding": "gzip, deflate, br",
808 | "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
809 | "Origin": "https://cart.jd.com",
810 | "Connection": "keep-alive"
811 | }
812 |
813 | resp = self.sess.post(url, data=data, headers=headers)
814 | if resp.status_code != requests.codes.OK:
815 | self.updateStateText('清空购物车勾选商品出错. status_code: %u, URL: %s.' % (resp.status_code, resp.url))
816 | return False
817 |
818 | self.updateStateText('清空购物车勾选商品成功!')
819 | return True
820 |
821 | def monitorMain(self):
822 | try:
823 | checkSession = requests.Session()
824 | checkSession.headers = {
825 | "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",
826 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
827 | "Connection": "keep-alive"
828 | }
829 | self.updateStateText('第 ' + str(self.cont) + ' 次查询:')
830 | self.cont += 1
831 | inStockSkuid = self.checkStock()
832 | soldOutNum = 0
833 | for skuId in inStockSkuid:
834 | if self.isSoldOut(skuId):
835 | self.updateStateText('%s 编号商品有货啦! 马上下单.' % skuId)
836 | skuidUrl = 'https://item.jd.com/' + skuId + '.html'
837 | if self.buyGoods(skuId):
838 | self.sendMail(skuidUrl, True)
839 | else:
840 | self.sendMail(skuidUrl, False)
841 | self.stopNow()
842 |
843 | else:
844 | if self.isMonitorSoldout == False:
845 | self.updateStateText('%s 编号商品已下架.' % skuId)
846 | self.skuid.remove(skuId)
847 | idBeg = self.skuidString.find(str(skuId))
848 | idEnd = idBeg + len(str(skuId))
849 | self.skuidString = self.skuidString[0:idBeg] + self.skuidString[idEnd + 1:]
850 | self.inputGoods.setText(self.skuidString)
851 | self.updateStateText('已将 %s 编号的下架商品清除, 并更新了商品编号输入框.' % skuId)
852 | self.selectAll()
853 | self.removeItem()
854 | else:
855 | soldOutNum += 1
856 | if soldOutNum != 0:
857 | self.updateStateText('监控的 %d 个商品已下架, 但当前模式保持监控.' % soldOutNum)
858 |
859 | if self.cont % 300 == 0:
860 | self.checkLogin()
861 | except Exception as e:
862 | import traceback
863 | self.updateStateText(traceback.format_exc())
864 |
865 | def updateStateText(self, stateText):
866 | # print(stateText)
867 | self.logger.info(stateText)
868 | self.textEdit.moveCursor(QtGui.QTextCursor.End)
869 | self.textEdit.insertPlainText(f'{time.ctime()} > ' + stateText + '\n')
870 |
871 | def main():
872 | app = QApplication(sys.argv)
873 | test = Autobuy()
874 | sys.exit(app.exec_())
875 |
876 |
877 |
878 | if __name__ == '__main__':
879 | main()
--------------------------------------------------------------------------------
/GUI Version/image/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/GUI Version/image/down.png
--------------------------------------------------------------------------------
/GUI Version/image/left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/GUI Version/image/left.png
--------------------------------------------------------------------------------
/GUI Version/image/right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/GUI Version/image/right.png
--------------------------------------------------------------------------------
/GUI Version/jdAutoBuyGood.log:
--------------------------------------------------------------------------------
1 | 2020-11-09 05:57:59,029 INFO: 正在验证登录状态...
2 | 2020-11-09 05:57:59,174 INFO: 第 1 次再尝试验证cookie...
3 | 2020-11-09 05:57:59,175 INFO: 正在尝试从历史讯息中恢复...
4 | 2020-11-09 05:57:59,177 INFO: [Errno 2] 没有那个文件或目录: 'cookie'
5 | 2020-11-09 05:57:59,178 INFO: 第 1 次再尝试验证cookie...
6 | 2020-11-09 05:57:59,315 INFO: 第 2 次再尝试验证cookie...
7 | 2020-11-09 05:57:59,316 INFO: 正在尝试从历史讯息中恢复...
8 | 2020-11-09 05:57:59,316 INFO: [Errno 2] 没有那个文件或目录: 'cookie'
9 | 2020-11-09 05:57:59,317 INFO: 第 2 次再尝试验证cookie...
10 | 2020-11-09 05:57:59,317 INFO: 请登录!
11 | 2020-11-09 05:58:13,244 INFO: 请您打开京东手机客户端或微信扫一扫, 准备扫码登录
12 | 2020-11-09 05:58:13,715 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
13 | 2020-11-09 05:58:15,853 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
14 | 2020-11-09 05:58:18,006 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
15 | 2020-11-09 05:58:20,136 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
16 | 2020-11-09 05:58:22,424 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
17 | 2020-11-09 05:58:24,565 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
18 | 2020-11-09 05:58:26,709 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
19 | 2020-11-09 05:58:28,855 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
20 | 2020-11-09 05:58:30,993 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
21 | 2020-11-09 05:58:33,133 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
22 | 2020-11-09 05:58:35,270 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
23 | 2020-11-09 05:58:37,501 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
24 | 2020-11-09 05:58:39,637 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
25 | 2020-11-09 05:58:41,775 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
26 | 2020-11-09 05:58:43,918 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
27 | 2020-11-09 05:58:46,061 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
28 | 2020-11-09 05:58:48,203 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
29 | 2020-11-09 05:58:50,347 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
30 | 2020-11-09 05:58:52,655 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
31 | 2020-11-09 05:58:54,789 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
32 | 2020-11-09 05:58:56,933 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
33 | 2020-11-09 05:58:59,064 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
34 | 2020-11-09 05:59:01,208 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
35 | 2020-11-09 05:59:03,348 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
36 | 2020-11-09 05:59:05,540 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
37 | 2020-11-09 05:59:07,871 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
38 | 2020-11-09 05:59:10,014 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
39 | 2020-11-09 05:59:12,183 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
40 | 2020-11-09 05:59:14,329 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
41 | 2020-11-09 05:59:16,463 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
42 | 2020-11-09 05:59:18,609 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
43 | 2020-11-09 05:59:20,765 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
44 | 2020-11-09 05:59:23,118 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
45 | 2020-11-09 05:59:25,254 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
46 | 2020-11-09 05:59:27,392 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
47 | 2020-11-09 05:59:29,529 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
48 | 2020-11-09 05:59:31,671 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
49 | 2020-11-09 05:59:33,812 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
50 | 2020-11-09 05:59:36,174 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
51 | 2020-11-09 05:59:38,531 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
52 | 2020-11-09 05:59:40,669 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
53 | 2020-11-09 05:59:42,804 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
54 | 2020-11-09 05:59:44,952 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
55 | 2020-11-09 05:59:47,094 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
56 | 2020-11-09 05:59:49,242 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
57 | 2020-11-09 05:59:51,488 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
58 | 2020-11-09 05:59:53,731 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
59 | 2020-11-09 05:59:55,874 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
60 | 2020-11-09 05:59:58,024 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
61 | 2020-11-09 06:00:00,167 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
62 | 2020-11-09 06:00:02,302 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
63 | 2020-11-09 06:00:04,447 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
64 | 2020-11-09 06:00:06,859 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
65 | 2020-11-09 06:00:09,329 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
66 | 2020-11-09 06:00:11,472 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
67 | 2020-11-09 06:00:13,609 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
68 | 2020-11-09 06:00:15,753 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
69 | 2020-11-09 06:00:17,886 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
70 | 2020-11-09 06:00:20,024 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
71 | 2020-11-09 06:00:22,258 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
72 | 2020-11-09 06:00:24,497 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
73 | 2020-11-09 06:00:26,638 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
74 | 2020-11-09 06:00:28,775 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
75 | 2020-11-09 06:00:30,923 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
76 | 2020-11-09 06:02:05,725 INFO: 请您打开京东手机客户端或微信扫一扫, 准备扫码登录
77 | 2020-11-09 06:02:06,231 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
78 | 2020-11-09 06:02:08,507 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
79 | 2020-11-09 06:02:10,653 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
80 | 2020-11-09 06:02:12,792 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
81 | 2020-11-09 06:02:14,939 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
82 | 2020-11-09 06:02:17,074 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
83 | 2020-11-09 06:02:19,214 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
84 | 2020-11-09 06:02:21,502 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
85 | 2020-11-09 06:02:23,738 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
86 | 2020-11-09 06:02:25,873 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
87 | 2020-11-09 06:02:28,006 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
88 | 2020-11-09 06:02:30,148 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
89 | 2020-11-09 06:02:32,295 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
90 | 2020-11-09 06:02:34,433 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
91 | 2020-11-09 06:02:36,655 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
92 | 2020-11-09 06:02:38,949 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
93 | 2020-11-09 06:02:41,096 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
94 | 2020-11-09 06:02:43,231 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
95 | 2020-11-09 06:02:45,365 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
96 | 2020-11-09 06:02:47,495 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
97 | 2020-11-09 06:02:49,628 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
98 | 2020-11-09 06:02:52,025 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
99 | 2020-11-09 06:02:54,268 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
100 | 2020-11-09 06:02:56,408 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
101 | 2020-11-09 06:02:58,550 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
102 | 2020-11-09 06:03:00,685 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
103 | 2020-11-09 06:03:02,825 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
104 | 2020-11-09 06:03:04,968 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
105 | 2020-11-09 06:03:07,280 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
106 | 2020-11-09 06:03:09,429 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
107 | 2020-11-09 06:03:11,561 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
108 | 2020-11-09 06:03:13,702 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
109 | 2020-11-09 06:03:15,838 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
110 | 2020-11-09 06:03:17,977 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
111 | 2020-11-09 06:03:20,128 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
112 | 2020-11-09 06:03:22,430 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
113 | 2020-11-09 06:03:24,567 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
114 | 2020-11-09 06:03:26,701 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
115 | 2020-11-09 06:03:28,839 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
116 | 2020-11-09 06:03:30,976 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
117 | 2020-11-09 06:03:33,114 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
118 | 2020-11-09 06:03:35,256 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
119 | 2020-11-09 06:03:37,485 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
120 | 2020-11-09 06:03:39,608 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
121 | 2020-11-09 06:03:41,750 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
122 | 2020-11-09 06:03:43,889 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
123 | 2020-11-09 06:03:46,030 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
124 | 2020-11-09 06:03:48,169 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
125 | 2020-11-09 06:03:50,312 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
126 | 2020-11-09 06:03:52,633 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
127 | 2020-11-09 06:03:54,775 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
128 | 2020-11-09 06:03:56,924 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
129 | 2020-11-09 06:03:59,067 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
130 | 2020-11-09 06:04:01,202 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
131 | 2020-11-09 06:04:03,334 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
132 | 2020-11-09 06:04:05,545 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
133 | 2020-11-09 06:04:07,767 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
134 | 2020-11-09 06:04:09,899 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
135 | 2020-11-09 06:04:12,041 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
136 | 2020-11-09 06:04:14,181 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
137 | 2020-11-09 06:04:16,319 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
138 | 2020-11-09 06:04:18,459 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
139 | 2020-11-09 06:04:20,699 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
140 | 2020-11-09 06:04:22,932 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
141 | 2020-11-09 06:04:25,073 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
142 | 2020-11-09 06:04:27,213 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
143 | 2020-11-09 06:04:29,354 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
144 | 2020-11-09 06:04:31,488 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
145 | 2020-11-09 06:04:33,630 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
146 | 2020-11-09 06:04:35,838 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
147 | 2020-11-09 06:04:38,167 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
148 | 2020-11-09 06:04:40,302 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
149 | 2020-11-09 06:04:42,444 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
150 | 2020-11-09 06:04:44,592 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
151 | 2020-11-09 06:04:46,725 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
152 | 2020-11-09 06:04:48,864 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
153 | 2020-11-09 06:04:50,998 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
154 | 2020-11-09 06:04:53,254 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
155 | 2020-11-09 06:04:55,396 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
156 | 2020-11-09 06:04:57,538 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
157 | 2020-11-09 06:04:59,680 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
158 | 2020-11-09 06:05:01,816 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
159 | 2020-11-09 06:05:03,955 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
160 | 2020-11-09 06:05:06,194 INFO: 二维码未扫描,请扫描二维码(Response Code: 201)
161 | 2020-11-09 06:05:08,544 INFO: 二维码过期,请重新扫描(Response Code: 203)
162 | 2020-11-09 06:05:10,691 INFO: 二维码过期,请重新扫描(Response Code: 203)
163 | 2020-11-09 06:05:12,827 INFO: 二维码过期,请重新扫描(Response Code: 203)
164 | 2020-11-09 06:05:14,965 INFO: 二维码过期,请重新扫描(Response Code: 203)
165 | 2020-11-09 06:05:17,109 INFO: 二维码过期,请重新扫描(Response Code: 203)
166 | 2020-11-09 06:05:19,250 INFO: 二维码过期,请重新扫描(Response Code: 203)
167 | 2020-11-09 06:05:21,617 INFO: 二维码过期,请重新扫描(Response Code: 203)
168 | 2020-11-09 06:05:23,869 INFO: 二维码过期,请重新扫描(Response Code: 203)
169 | 2020-11-09 06:05:26,008 INFO: 二维码过期,请重新扫描(Response Code: 203)
170 | 2020-11-09 06:05:28,157 INFO: 二维码过期,请重新扫描(Response Code: 203)
171 | 2020-11-09 06:05:30,299 INFO: 二维码过期,请重新扫描(Response Code: 203)
172 | 2020-11-09 06:05:32,436 INFO: 二维码过期,请重新扫描(Response Code: 203)
173 | 2020-11-09 06:05:34,572 INFO: 二维码过期,请重新扫描(Response Code: 203)
174 | 2020-11-09 06:05:36,873 INFO: 二维码过期,请重新扫描(Response Code: 203)
175 | 2020-11-09 06:05:39,040 INFO: 二维码过期,请重新扫描(Response Code: 203)
176 | 2020-11-09 06:05:41,165 INFO: 二维码过期,请重新扫描(Response Code: 203)
177 | 2020-11-09 06:05:43,315 INFO: 二维码过期,请重新扫描(Response Code: 203)
178 | 2020-11-09 06:05:45,455 INFO: 二维码过期,请重新扫描(Response Code: 203)
179 |
--------------------------------------------------------------------------------
/GUI Version/qr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/GUI Version/qr.png
--------------------------------------------------------------------------------
/GUI Version/window.qss:
--------------------------------------------------------------------------------
1 | /*
2 | Notice:
3 | 01 注释只能用多行注释,单行注释会出错
4 | */
5 | /*******定义字体,背景颜色*********/
6 | *{
7 | font: "微软雅黑";
8 | color: rgb(220, 220, 220);
9 | background-color: rgb(68, 68, 68);
10 | border-radius: 2px;
11 | padding: 3px;
12 | margin: 2px;
13 | }
14 | /****************定义边框*****************/
15 | QLineEdit, QPushButton, QTimeEdit,
16 | QSpinBox, QDoubleSpinBox, QComboBox,
17 | QDateEdit, QDateTimeEdit, QGroupBox,
18 | QTextEdit, QTabWidget {
19 | border:1px solid rgb(36, 36, 36);
20 | }
21 | /*************菜单下拉按钮*****************/
22 | QMenu::item {
23 | background-color: transparent;
24 | }
25 | /********菜单下拉按钮(被选择时)***********/
26 | QMenu::item:selected {
27 | background-color: rgb(100, 100, 100);
28 | }
29 | /****************定义菜单栏***************/
30 | QMenuBar {
31 | border-radius: 0;
32 | background-color: rgb(72, 72, 72);
33 | border-bottom: 1px solid rgb(36, 36, 36);
34 | }
35 | /************菜单栏按钮(被选择时)********/
36 | QMenuBar::item:selected {
37 | background-color: rgb(100, 100, 100);
38 | }
39 | /************菜单栏按钮(鼠标悬停)********/
40 | QMenu:hover {
41 | background-color: rgb(100, 100, 100);
42 | }
43 | /*********按钮(渐变:突出显示)***********/
44 | QPushButton {
45 | border-style: inset;
46 | background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(72, 72, 72, 255), stop:1 rgba(56, 56, 56, 255));
47 | border:1px solid rgb(36, 36, 36);
48 | border-radius: 6px;
49 | min-width: 5em;
50 | min-height: 1em;
51 | padding: 6px 6px;
52 | margin: 5px
53 | }
54 | /**************按钮(鼠标悬停)**********/
55 | QPushButton:hover {
56 | background-color: rgb(91, 91, 91);
57 | }
58 | /**************按钮(按下)*************/
59 | QPushButton:pressed {
60 | background-color: rgb(68, 68, 68);
61 | }
62 | QSpinBox::up-button, QTimeEdit::up-button,
63 | QDateEdit::up-button, QDateTimeEdit::up-button,
64 | QDoubleSpinBox::up-button {
65 | subcontrol-position: right;
66 | border: 0px;
67 | }
68 | QSpinBox::down-button, QTimeEdit::down-button,
69 | QDateEdit::down-button, QDateTimeEdit::down-button,
70 | QDoubleSpinBox::down-button {
71 | subcontrol-position: left;
72 | border: 0px;
73 | }
74 | QSpinBox::up-arrow, QTimeEdit::up-arrow,
75 | QDateEdit::up-arrow, QDateTimeEdit::up-arrow,
76 | QDoubleSpinBox::up-arrow {
77 | image: url(image/right.png);
78 | }
79 | QSpinBox::down-arrow, QTimeEdit::down-arrow,
80 | QDateEdit::down-arrow, QDateTimeEdit::down-arrow,
81 | QDoubleSpinBox::down-arrow {
82 | image: url(image/left.png);
83 | }
84 | /*********定义Slider槽的形态**************/
85 | QSlider::groove:horizontal {
86 | height: 6px;
87 | border-radius: 3px;
88 | }
89 | /*********定义Slider柄的形态**************/
90 | QSlider::handle:horizontal {
91 | background-color: rgb(68, 68, 68);
92 | border-radius: 5px;
93 | border: 2px solid rgb(36, 36, 36);
94 | height: 8px;
95 | width: 8px;
96 | margin: -3px -3px;
97 | }
98 | /*********定义handle右边的背景**************/
99 | QSlider::add-page:horizontal{
100 | background: rgb(72, 72, 72);
101 | }
102 | /*********定义handle左边的背景**************/
103 | QSlider::sub-page:horizontal{
104 | background: rgb(36, 36, 36);
105 | }
106 | /****************定义进度条****************/
107 | QProgressBar {
108 | border: 2px solid grey;
109 | border-radius: 5px;
110 | text-align: center;
111 | height: 12px;
112 | }
113 | /*************定义进度条背景**************/
114 | QProgressBar::chunk {
115 | background-color: rgb(128, 128, 128);
116 | width: 8px;
117 | margin: 0.5px;
118 | }
119 |
120 | QTabWidget::pane { /* The tab widget frame */
121 | border: 1px solid rgb(36, 36, 36);
122 | }
123 | QTabWidget::tab-bar {
124 | border: 1px solid rgb(36, 36, 36);
125 | }
126 | QTabBar::tab {
127 | background: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(100, 100, 100, 255), stop:1 rgba(82, 82, 82, 255));
128 | border: 1px solid rgb(36, 36, 36);
129 | border-bottom-color: #C2C7CB; /* same as the pane color */
130 | min-width: 12ex;
131 | min-height: 6ex;
132 | padding: 2px 4px;
133 | }
134 | QTabBar::tab:selected, QTabBar::tab:hover {
135 | border-top: 2px solid red;
136 | padding-top: 3px;
137 | background: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 rgba(72, 72, 72, 255), stop:1 rgba(56, 56, 56, 255));
138 | }
139 | /*************QComboBox******************/
140 | QComboBox::drop-down {
141 | subcontrol-origin: padding;
142 | subcontrol-position: top right;
143 | width: 20px;
144 | border: 0px;
145 | }
146 | QComboBox::down-arrow {
147 | image: url(image/down.png);
148 | }
149 | QComboBox::down-arrow:on { /* shift the arrow when popup is open */
150 | top: 1px;
151 | left: 1px;
152 | }
153 | /*********下拉列表的item背景***************/
154 | QComboBox QAbstractItemView {
155 | border: 0px;
156 | selection-background-color: rgb(100, 100, 100);
157 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Yikai Zhang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # auto-buy-Python-tool
2 | 图形界面, 电脑小白也会用, 下载可直接运行! 京东自动购买口罩 实时抢购口罩 工具, 抗击疫情 中国加油!
3 |
4 | `4.0` :fire:
5 |
6 | 点击这里 下载`JDAutoBuy-release.zip`, 解压后可**直接运行!**
7 |
8 | ### 欢迎加星
9 |
10 | > 修复了商品下架后的问题, 更新了交互界面; 修复了可配货商品的判断, 更新了数量调整接口, 更新了是否监控下架商品选项
11 |
12 | :star2:
13 |
14 |
15 |
16 |
17 |
18 | ## 使用指南
19 |
20 | ### :notebook_with_decorative_cover: Tips: 登录一次之后本地会保存登录信息, 重启软件(注意重启之后也行)之后仍然可以记住账号登录信息, 重启之后只需点击"开始监控"就可以登录! 不必重复扫码!
21 |
22 | 运行界面**如下图**:
23 |
24 | 
25 |
26 | Update at 2020-3-2: Continuously monitor goods removed from JD.
27 |
28 | Update at 2020-2-15: quantity can be modified
29 |
30 | ### 填写方式:
31 |
32 | Tips: 软件启动时带有标准填写格式的默认值, 请留意.
33 |
34 | + **输入商品ID:** 比如`URL`为: https://item.jd.com/1835967.html 的商品ID为**1835967**.
35 | + **输入收件地区编码**: 使用Chrome浏览器(如果是其他浏览器请用同样方式打开**开发者工具**)登录京东并访问商品页, 选择派送地址后按`F12`查找`stock?`开头的`URL`讯息, 如下图: 
36 | + **接受讯息邮箱**: 您的接受讯息邮箱.
37 | + **滑动条**: 控制监控时查询的速度(频率).
38 | + **购买数量**: 调整一次购买数量.
39 | + **是否自动忽略下架商品**: 未打勾 - 下架商品上架时立即抢购, 打勾 - 自动忽略下架商品并删除.
40 |
41 |
42 |
43 | 以下选项您可以不看也会使用:
44 |
45 | **扫码登录**: 如果京东手机客户端无法扫码, 请用**微信**扫一扫试一下.
46 |
47 | **开始监控**: 如果**未登录点击此按钮**, 您之前登录成功过则会读取历史登录记录尝试登录, 否则会提示您先扫码登录.
48 |
49 | 以下是有货时购买的界面, 祝您成功.
50 |
51 | 
52 |
53 | 更新后`2.0`运行界面:
54 |
55 | 
56 |
57 | Update at 2020-2-15 20:06:14: 最近比较难抢了, 因为京东一些商品是预约完再抢购, 预约完之后即被放入购物车, 导致监控有货无货较困难. 见谅.
58 |
59 | ---
60 |
61 | ## 以下是控制台版本程序的说明, 如果您使用图形界面版本, 可以不看
62 |
63 | **获取登录*cookie***: Chrome 登录京东后`F12`, 如下图.
64 |
65 | 
66 |
67 |
68 |
69 | **获取商品URL**: 登录并访问商品页, 选择派送地址后查找**stock?**开头的URL讯息, 如下图.
70 |
71 | 
72 |
73 | 请注意商品`URL`需要是您的地址编号, 如TXT文件中`area=`参数.
74 |
75 |
76 |
77 | **以上两步**获得的讯息填入`Please fill out this document.txt`文件.
78 |
79 | ```shell
80 | pip install -r requirements.txt
81 | python JDAutoBuyTool.py
82 | ```
83 |
84 |
85 |
86 | **运行环境**:
87 |
88 | `Windows 10, Python 3`
89 |
90 | **运行示例**:
91 |
92 | 
93 |
94 | ---
95 |
96 | 感谢[cycz](https://github.com/cycz)大佬, 参考了部分代码.
97 |
98 | 心情复杂, 也不懂抢口罩工具能不能帮上忙, **一定能尽快战胜疫情! 中国加油!** :star2:
--------------------------------------------------------------------------------
/assets/1580963259089.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1580963259089.png
--------------------------------------------------------------------------------
/assets/1580963623908.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1580963623908.png
--------------------------------------------------------------------------------
/assets/1581038258274.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581038258274.png
--------------------------------------------------------------------------------
/assets/1581218076866.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581218076866.png
--------------------------------------------------------------------------------
/assets/1581218537205.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581218537205.png
--------------------------------------------------------------------------------
/assets/1581249279630.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581249279630.png
--------------------------------------------------------------------------------
/assets/1581508416184.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581508416184.png
--------------------------------------------------------------------------------
/assets/1581508444771.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581508444771.png
--------------------------------------------------------------------------------
/assets/1581768204211.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581768204211.png
--------------------------------------------------------------------------------
/assets/1581768213048.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1581768213048.png
--------------------------------------------------------------------------------
/assets/1583151909197.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jjjenkinson/autobuy-jd/1834e6d14b598f352ca71665335a3e2979e9eeb9/assets/1583151909197.png
--------------------------------------------------------------------------------