Python爬虫,自动登录京东网站,查询商品库存,价格,显示购物车详情等。
可以指定抢购商品,自动购买下单,然后手动去京东付款就行。
chang log
2017-03-30 实现二维码扫码登陆
2017-06-27 Golang版JD_AutoBuy
运行环境
Python 2.7
Requests: 简单好用,功能强大的Http请求库
beautifulsoup4: HTML文档格式化及便签选择器
1 pip install requests
2 pip install beautifulsoup4
1 # -- coding: utf-8 --
2
3 “”"
4 JD online shopping helper tool
5 -----------------------------------------------------
6 only support to login by QR code,
7 username / password is not working now.
8 “”"
9
10
11 import bs4
12 import requests, requests.utils, pickle
13 import requests.packages.urllib3
14 requests.packages.urllib3.disable_warnings()
15
16 import os
17 import time
18 import json
19 import random
20
21
22 import argparse
23 #from selenium import webdriver
24
25
26 import sys
27 reload(sys)
28 sys.setdefaultencoding(‘utf-8’)
29
30 # get function name
31 FuncName = lambda n=0: sys._getframe(n + 1).f_code.co_name
32
33
34 def tags_val(tag, key=’’, index=0):
35 ‘’’
36 return html tag list attribute @key @index
37 if @key is empty, return tag content
38 ‘’’
39 if len(tag) == 0 or len(tag) <= index:
40 return ‘’
41 elif key:
42 txt = tag[index].get(key)
43 return txt.strip(’ \t\r\n’) if txt else ‘’
44 else:
45 txt = tag[index].text
46 return txt.strip(’ \t\r\n’) if txt else ‘’
47
48
49 def tag_val(tag, key=’’):
50 ‘’’
51 return html tag attribute @key
52 if @key is empty, return tag content
53 ‘’’
54 if tag is None:
55 return ‘’
56 elif key:
57 txt = tag.get(key)
58 return txt.strip(’ \t\r\n’) if txt else ‘’
59 else:
60 txt = tag.text
61 return txt.strip(’ \t\r\n’) if txt else ‘’
62
63
64 class JDWrapper(object):
65 ‘’’
66 This class used to simulate login JD
67 ‘’’
68
69 def init(self, usr_name=None, usr_pwd=None):
70 # cookie info
71 self.trackid = ‘’
72 self.uuid = ‘’
73 self.eid = ‘’
74 self.fp = ‘’
75
76 self.usr_name = usr_name
77 self.usr_pwd = usr_pwd
78
79 self.interval = 0
80
81 # init url related
82 self.home = ‘https://passport.jd.com/new/login.aspx’
83 self.login = ‘https://passport.jd.com/uc/loginService’
84 self.imag = ‘https://authcode.jd.com/verify/image’
85 self.auth = ‘https://passport.jd.com/uc/showAuthCode’
86
87 self.sess = requests.Session()
88
89 self.headers = {
90 ‘User-Agent’ : ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36’,
91 ‘ContentType’: ‘text/html; charset=utf-8’,
92 ‘Accept-Encoding’:‘gzip, deflate, sdch’,
93 ‘Accept-Language’:‘zh-CN,zh;q=0.8’,
94 ‘Connection’ : ‘keep-alive’,
95 }
96
97 self.cookies = {
98
99 }
100
101 ‘’’
102 try:
103 self.browser = webdriver.PhantomJS(‘phantomjs.exe’)
104 except Exception, e:
105 print ‘Phantomjs initialize failed :’, e
106 exit(1)
107 ‘’’
108
109 @staticmethod
110 def print_json(resp_text):
111 ‘’’
112 format the response content
113 ‘’’
114 if resp_text[0] == ‘(’:
115 resp_text = resp_text[1:-1]
116
117 for k,v in json.loads(resp_text).items():
118 print u’%s : %s’ % (k, v)
119
120 @staticmethod
121 def response_status(resp):
122 if resp.status_code != requests.codes.OK:
123 print ‘Status: %u, Url: %s’ % (resp.status_code, resp.url)
124 return False
125 return True
126
127 def _need_auth_code(self, usr_name):
128 # check if need auth code
129 #
130 auth_dat = {
131 ‘loginName’: usr_name,
132 }
133 payload = {
134 ‘r’ : random.random(),
135 ‘version’ : 2015
136 }
137
138 resp = self.sess.post(self.auth, data=auth_dat, params=payload)
139 if self.response_status(resp) :
140 js = json.loads(resp.text[1:-1])
141 return js[‘verifycode’]
142
143 print u’获取是否需要验证码失败’
144 return False
145
146 def get_auth_code(self, uuid):
147 # image save path
148 image_file = os.path.join(os.getcwd(), ‘authcode.jfif’)
149
150 payload = {
151 ‘a’ : 1,
152 ‘acid’ : uuid,
153 ‘uid’ : uuid,
154 ‘yys’ : str(int(time.time() * 1000)),
155 }
156
157 # get auth code
158 r = self.sess.get(self.imag, params=payload)
159 if not self.response_status®:
160 print u’获取验证码失败’
161 return False
162
163 with open (image_file, ‘wb’) as f:
164 for chunk in r.iter_content(chunk_size=1024):
165 f.write(chunk)
166
167 f.close()
168
169 os.system(‘start ’ + image_file)
170 return str(raw_input(‘Auth Code: ‘))
171
172 def login_once(self, login_data):
173 # url parameter
174 payload = {
175 ‘r’: random.random(),
176 ‘uuid’ : login_data[‘uuid’],
177 ‘version’ : 2015,
178 }
179
180 resp = self.sess.post(self.login, data=login_data, params=payload)
181 if self.response_status(resp):
182 js = json.loads(resp.text[1:-1])
183 #self.print_json(resp.text)
184
185 if not js.get(‘success’) :
186 print js.get(‘emptyAuthcode’)
187 return False
188 else:
189 return True
190
191 return False
192
193 def login_try(self):
194 “”" login by username and password, but not working now.
195
196 … deprecated::
197 Use login_by_QR
198 “”"
199 # get login page
200 #resp = self.sess.get(self.home)
201 print ‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++’
202 print u’{0} > 登陆’.format(time.ctime())
203
204 try:
205 # 2016/09/17 PhantomJS can’t login anymore
206 self.browser.get(self.home)
207 soup = bs4.BeautifulSoup(self.browser.page_source, “html.parser”)
208
209 # set cookies from PhantomJS
210 for cookie in self.browser.get_cookies():
211 self.sess.cookies[cookie[‘name’]] = str(cookie[‘value’])
212
213 #for (k, v) in self.sess.cookies.items():
214 # print ‘%s: %s’ % (k, v)
215
216 # response data hidden input == 9 ??. Changed
217 inputs = soup.select(‘form#formlogin input[type=hidden]’)
218 rand_name = inputs[-1][‘name’]
219 rand_data = inputs[-1][‘value’]
220 token = ‘’
221
222 for idx in range(len(inputs) - 1):
223 id = inputs[idx][‘id’]
224 va = inputs[idx][‘value’]
225 if id == ‘token’:
226 token = va
227 elif id == ‘uuid’:
228 self.uuid = va
229 elif id == ‘eid’:
230 self.eid = va
231 elif id == ‘sessionId’:
232 self.fp = va
233
234 auth_code = ‘’
235 if self.need_auth_code(self.usr_name):
236 auth_code = self.get_auth_code(self.uuid)
237 else:
238 print u’无验证码登陆’
239
240 login_data = {
241 ‘t’: token,
242 ‘authcode’: auth_code,
243 ‘chkRememberMe’: ‘on’,
244 ‘loginType’: ‘f’,
245 ‘uuid’: self.uuid,
246 ‘eid’: self.eid,
247 ‘fp’: self.fp,
248 ‘nloginpwd’: self.usr_pwd,
249 ‘loginname’: self.usr_name,
250 ‘loginpwd’: self.usr_pwd,
251 rand_name : rand_data,
252 }
253
254 login_succeed = self.login_once(login_data)
255 if login_succeed:
256 self.trackid = self.sess.cookies[‘TrackID’]
257 print u’登陆成功 %s’ % self.usr_name
258 else:
259 print u’登陆失败 %s’ % self.usr_name
260
261 return login_succeed
262
263 except Exception, e:
264 print ‘Exception:’, e.message
265 raise
266 finally:
267 self.browser.quit()
268
269 return False
270
271 def checkLogin(self):
272 checkUrl = ‘https://passport.jd.com/uc/qrCodeTicketValidation’
273
274 try:
275 print ‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++’
276 print u’{0} > 自动登录中… ‘.format(time.ctime())
277 with open(‘cookie’, ‘rb’) as f:
278 cookies = requests.utils.cookiejar_from_dict(pickle.load(f))
279 resp = requests.get(checkUrl, cookies=cookies)
280
281 if resp.status_code != requests.codes.OK:
282 print u’登录过期, 请重新登录!’
283 return False
284 else:
285 return True
286
287 return False
288 except Exception as e:
289 return False
290 else:
291 pass
292 finally:
293 pass
294
295 return False
296
297 def login_by_QR(self):
298 # jd login by QR code
299 try:
300 print ‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++’
301 print u’{0} > 请打开京东手机客户端,准备扫码登陆:’.format(time.ctime())
302
303 urls = (
304 ‘https://passport.jd.com/new/login.aspx’,
305 ‘https://qr.m.jd.com/show’,
306 ‘https://qr.m.jd.com/check’,
307 ‘https://passport.jd.com/uc/qrCodeTicketValidation’
308 )
309
310 # step 1: open login page
311 resp = self.sess.get(
312 urls[0],
313 headers = self.headers
314 )
315 if resp.status_code != requests.codes.OK:
316 print u’获取登录页失败: %u’ % resp.status_code
317 return False
318
319 ## save cookies
320 for k, v in resp.cookies.items():
321 self.cookies[k] = v
322
323
324 # step 2: get QR image
325 resp = self.sess.get(
326 urls[1],
327 headers = self.headers,
328 cookies = self.cookies,
329 params = {
330 ‘appid’: 133,
331 ‘size’: 147,
332 ‘t’: (long)(time.time() * 1000)
333 }
334 )
335 if resp.status_code != requests.codes.OK:
336 print u’获取二维码失败: %u’ % resp.status_code
337 return False
338
339 ## save cookies
340 for k, v in resp.cookies.items():
341 self.cookies[k] = v
342
343 ## save QR code
344 image_file = ‘qr.png’
345 with open (image_file, ‘wb’) as f:
346 for chunk in resp.iter_content(chunk_size=1024):
347 f.write(chunk)
348
349 ## scan QR code with phone
350 if os.name == “nt”:
351 # for windows
352 os.system('start ’ + image_file)
353 else:
354 if os.uname()[0] == “Linux”:
355 # for linux platform
356 os.system("eog " + image_file)
357 else:
358 # for Mac platform
359 os.system("open " + image_file)
360
361 # step 3: check scan result
362 ## mush have
363 self.headers[‘Host’] = ‘qr.m.jd.com’
364 self.headers[‘Referer’] = ‘https://passport.jd.com/new/login.aspx’
365
366 # check if QR code scanned
367 qr_ticket = None
368 retry_times = 100
369 while retry_times:
370 retry_times -= 1
371 resp = self.sess.get(
372 urls[2],
373 headers = self.headers,
374 cookies = self.cookies,
375 params = {
376 ‘callback’: ‘jQuery%u’ % random.randint(100000, 999999),
377 ‘appid’: 133,
378 ‘token’: self.cookies[‘wlfstk_smdl’],
379 '’: (long)(time.time() * 1000)
380 }
381 )
382
383 if resp.status_code != requests.codes.OK:
384 continue
385
386 n1 = resp.text.find(’(’)
387 n2 = resp.text.find(’)’)
388 rs = json.loads(resp.text[n1+1:n2])
389
390 if rs[‘code’] == 200:
391 print u’{} : {}’.format(rs[‘code’], rs[‘ticket’])
392 qr_ticket = rs[‘ticket’]
393 break
394 else:
395 print u’{} : {}’.format(rs[‘code’], rs[‘msg’])
396 time.sleep(3)
397
398 if not qr_ticket:
399 print u’二维码登陆失败’
400 return False
401
402 # step 4: validate scan result
403 ## must have
404 self.headers[‘Host’] = ‘passport.jd.com’
405 self.headers[‘Referer’] = ‘https://passport.jd.com/uc/login?ltype=logout’
406 resp = self.sess.get(
407 urls[3],
408 headers = self.headers,
409 cookies = self.cookies,
410 params = {‘t’ : qr_ticket },
411 )
412 if resp.status_code != requests.codes.OK:
413 print u’二维码登陆校验失败: %u’ % resp.status_code
414 return False
415
416 ## 京东有时候会认为当前登录有危险,需要手动验证
417 ## url: https://safe.jd.com/dangerousVerify/index.action?username=…
418 res = json.loads(resp.text)
419 if not resp.headers.get(‘P3P’):
420 if res.has_key(‘url’):
421 print u’需要手动安全验证: {0}’.format(res[‘url’])
422 return False
423 else:
424 print_json(res)
425 print u’登陆失败!!’
426 return False
427
428 ## login succeed
429 self.headers[‘P3P’] = resp.headers.get(‘P3P’)
430 for k, v in resp.cookies.items():
431 self.cookies[k] = v
432
433 with open(‘cookie’, ‘wb’) as f:
434 pickle.dump(self.cookies, f)
435
436 print u’登陆成功’
437 return True
438
439 except Exception as e:
440 print ‘Exp:’, e
441 raise
442
443 return False
444
445
446 def good_stock(self, stock_id, good_count=1, area_id=None):
447 ‘’’
448 33 : on sale,
449 34 : out of stock
450 ‘’’
451 # http://ss.jd.com/ss/areaStockState/mget?app=cart_pc&ch=1&skuNum=3180350,1&area=1,72,2799,0
452 # response: {“3180350”:{“a”:“34”,“b”:“1”,“c”:"-1"}}
453 #stock_url = ‘http://ss.jd.com/ss/areaStockState/mget’
454
455 # http://c0.3.cn/stocks?callback=jQuery2289454&type=getstocks&skuIds=3133811&area=1_72_2799_0&=1490694504044
456 # jQuery2289454({“3133811”:{“StockState”:33,“freshEdi”:null,“skuState”:1,“PopType”:0,“sidDely”:“40”,“channel”:1,“StockStateName”:“现货”,“rid”:null,“rfg”:0,“ArrivalDate”:"",“IsPurchase”:true,“rn”:-1}})
457 # jsonp or json both work
458 stock_url = ‘https://c0.3.cn/stocks’
459
460 payload = {
461 ‘type’ : ‘getstocks’,
462 ‘skuIds’ : str(stock_id),
463 ‘area’ : area_id or ‘1_72_2799_0’, # area change as needed
464 }
465
466 try:
467 # get stock state
468 resp = self.sess.get(stock_url, params=payload)
469 if not self.response_status(resp):
470 print u’获取商品库存失败’
471 return (0, ‘’)
472
473 # return json
474 resp.encoding = ‘gbk’
475 stock_info = json.loads(resp.text)
476 stock_stat = int(stock_info[stock_id][‘StockState’])
477 stock_stat_name = stock_info[stock_id][‘StockStateName’]
478
479 # 33 : on sale, 34 : out of stock, 36: presell
480 return stock_stat, stock_stat_name
481
482 except Exception as e:
483 print ‘Stocks Exception:’, e
484 time.sleep(5)
485
486 return (0, ‘’)
487
488
489 def good_detail(self, stock_id, area_id=None):
490 # return good detail
491 good_data = {
492 ‘id’ : stock_id,
493 ‘name’ : ‘’,
494 ‘link’ : ‘’,
495 ‘price’ : ‘’,
496 ‘stock’ : ‘’,
497 ‘stockName’: ‘’,
498 }
499
500 try:
501 # shop page
502 stock_link = ‘http://item.jd.com/{0}.html’.format(stock_id)
503 resp = self.sess.get(stock_link)
504
505 # good page
506 soup = bs4.BeautifulSoup(resp.text, “html.parser”)
507
508 # good name
509 tags = soup.select(‘div#name h1’)
510 if len(tags) == 0:
511 tags = soup.select(‘div.sku-name’)
512 good_data[‘name’] = tags_val(tags).strip(’ \t\r\n’)
513
514 # cart link
515 tags = soup.select(‘a#InitCartUrl’)
516 link = tags_val(tags, key=‘href’)
517
518 if link[:2] == ‘//’: link = ‘http:’ + link
519 good_data[‘link’] = link
520
521 except Exception, e:
522 print ‘Exp {0} : {1}’.format(FuncName(), e)
523
524 # good price
525 good_data[‘price’] = self.good_price(stock_id)
526
527 # good stock
528 good_data[‘stock’], good_data[‘stockName’] = self.good_stock(stock_id=stock_id, area_id=area_id)
529 #stock_str = u’有货’ if good_data[‘stock’] == 33 else u’无货’
530
531 print ‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++’
532 print u’{0} > 商品详情’.format(time.ctime())
533 print u’编号:{0}’.format(good_data[‘id’])
534 print u’库存:{0}’.format(good_data[‘stockName’])
535 print u’价格:{0}’.format(good_data[‘price’])
536 print u’名称:{0}’.format(good_data[‘name’])
537 #print u’链接:{0}’.format(good_data[‘link’])
538
539 return good_data
540
541
542 def good_price(self, stock_id):
543 # get good price
544 url = ‘http://p.3.cn/prices/mgets’
545 payload = {
546 ‘type’ : 1,
547 ‘pduid’ : int(time.time() * 1000),
548 ‘skuIds’ : 'J’ + stock_id,
549 }
550
551 price = ‘?’
552 try:
553 resp = self.sess.get(url, params=payload)
554 resp_txt = resp.text.strip()
555 #print resp_txt
556
557 js = json.loads(resp_txt[1:-1])
558 #print u’价格’, ‘P: {0}, M: {1}’.format(js[‘p’], js[‘m’])
559 price = js.get(‘p’)
560
561 except Exception, e:
562 print ‘Exp {0} : {1}’.format(FuncName(), e)
563
564 return price
565
566
567 def buy(self, options):
568 # stock detail
569 good_data = self.good_detail(options.good)
570
571 # retry until stock not empty
572 if good_data[‘stock’] != 33:
573 # flush stock state
574 while good_data[‘stock’] != 33 and options.flush:
575 print u’<%s> <%s>’ % (good_data[‘stockName’], good_data[‘name’])
576 time.sleep(options.wait / 1000.0)
577 good_data[‘stock’], good_data[‘stockName’] = self.good_stock(stock_id=options.good, area_id=options.area)
578
579 # retry detail
580 #good_data = self.good_detail(options.good)
581
582
583 # failed
584 link = good_data[‘link’]
585 if good_data[‘stock’] != 33 or link == ‘’:
586 #print u’stock {0}, link {1}’.format(good_data[‘stock’], link)
587 return False
588
589 try:
590 # change buy count
591 if options.count != 1:
592 link = link.replace(‘pcount=1’, ‘pcount={0}’.format(options.count))
593
594 # add to cart
595 resp = self.sess.get(link, cookies = self.cookies)
596 soup = bs4.BeautifulSoup(resp.text, “html.parser”)
597
598 # tag if add to cart succeed
599 tag = soup.select(‘h3.ftx-02’)
600 if tag is None:
601 tag = soup.select(‘div.p-name a’)
602
603 if tag is None or len(tag) == 0:
604 print u’添加到购物车失败’
605 return False
606
607 print ‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++’
608 print u’{0} > 购买详情’.format(time.ctime())
609 print u’链接:{0}’.format(link)
610 print u’结果:{0}’.format(tags_val(tag))
611
612 # change count after add to shopping cart
613 #self.buy_good_count(options.good, options.count)
614
615 except Exception, e:
616 print ‘Exp {0} : {1}’.format(FuncName(), e)
617 else:
618 self.cart_detail()
619 return self.order_info(options.submit)
620
621 return False
622
623 def buy_good_count(self, good_id, count):
624 url = ‘http://cart.jd.com/changeNum.action’
625
626 payload = {
627 ‘venderId’: ‘8888’,
628 ‘pid’: good_id,
629 ‘pcount’: count,
630 ‘ptype’: ‘1’,
631 ‘targetId’: ‘0’,
632 ‘promoID’:‘0’,
633 ‘outSkus’: ‘’,
634 ‘random’: random.random(),
635 ‘locationId’:‘1-72-2799-0’, # need changed to your area location id
636 }
637
638 try:
639 rs = self.sess.post(url, params = payload, cookies = self.cookies)
640 if rs.status_code == 200:
641 js = json.loads(rs.text)
642 if js.get(‘pcount’):
643 print u’数量:%s @ %s’ % (js[‘pcount’], js[‘pid’])
644 return True
645 else:
646 print u’购买 %d 失败’ % count
647
648 except Exception, e:
649 print ‘Exp {0} : {1}’.format(FuncName(), e)
650
651 return False
652
653
654 def cart_detail(self):
655 # list all goods detail in cart
656 cart_url = ‘https://cart.jd.com/cart.action’
657 cart_header = u’购买 数量 价格 总价 商品’
658 cart_format = u’{0:8}{1:8}{2:12}{3:12}{4}’
659
660 try:
661 resp = self.sess.get(cart_url, cookies = self.cookies)
662 resp.encoding = ‘utf-8’
663 soup = bs4.BeautifulSoup(resp.text, “html.parser”)
664
665 print ‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++’
666 print u’{0} > 购物车明细’.format(time.ctime())
667 print cart_header
668
669 for item in soup.select(‘div.item-form’):
670 check = tags_val(item.select(‘div.cart-checkbox input’), key=‘checked’)
671 check = ’ + ’ if check else ’ - ’
672 count = tags_val(item.select(‘div.quantity-form input’), key=‘value’)
673 price = tags_val(item.select(‘div.p-price strong’))
674 sums = tags_val(item.select(‘div.p-sum strong’))
675 gname = tags_val(item.select(‘div.p-name a’))
676 #: ¥字符解析出错, 输出忽略¥
677 print cart_format.format(check, count, price[1:], sums[1:], gname)
678
679 t_count = tags_val(soup.select(‘div.amount-sum em’))
680 t_value = tags_val(soup.select(‘span.sumPrice em’))
681 print u’总数: {0}’.format(t_count)
682 print u’总额: {0}’.format(t_value[1:])
683
684 except Exception, e:
685 print ‘Exp {0} : {1}’.format(FuncName(), e)
686
687
688 def order_info(self, submit=False):
689 # get order info detail, and submit order
690 print ‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++’
691 print u’{0} > 订单详情’.format(time.ctime())
692
693 try:
694 order_url = ‘http://trade.jd.com/shopping/order/getOrderInfo.action’
695 payload = {
696 ‘rid’ : str(int(time.time() * 1000)),
697 }
698
699 # get preorder page
700 rs = self.sess.get(order_url, params=payload, cookies = self.cookies)
701 soup = bs4.BeautifulSoup(rs.text, “html.parser”)
702
703 # order summary
704 payment = tag_val(soup.find(id=‘sumPayPriceId’))
705 detail = soup.find(class=‘fc-consignee-info’)
706
707 if detail:
708 snd_usr = tag_val(detail.find(id=‘sendMobile’))
709 snd_add = tag_val(detail.find(id=‘sendAddr’))
710
711 print u’应付款:{0}’.format(payment)
712 print snd_usr
713 print snd_add
714
715 # just test, not real order
716 if not submit:
717 return False
718
719 # order info
720 payload = {
721 ‘overseaPurchaseCookies’: ‘’,
722 ‘submitOrderParam.btSupport’: ‘1’,
723 ‘submitOrderParam.ignorePriceChange’: ‘0’,
724 ‘submitOrderParam.sopNotPutInvoice’: ‘false’,
725 ‘submitOrderParam.trackID’: self.trackid,
726 ‘submitOrderParam.eid’: self.eid,
727 ‘submitOrderParam.fp’: self.fp,
728 }
729
730 order_url = ‘http://trade.jd.com/shopping/order/submitOrder.action’
731 rp = self.sess.post(order_url, params=payload, cookies = self.cookies)
732
733 if rp.status_code == 200:
734 js = json.loads(rp.text)
735 if js[‘success’] == True:
736 print u’下单成功!订单号:{0}’.format(js[‘orderId’])
737 print u’请前往东京官方商城付款’
738 return True
739 else:
740 print u’下单失败!<{0}: {1}>’.format(js[‘resultCode’], js[‘message’])
741 if js[‘resultCode’] == ‘60017’:
742 # 60017: 您多次提交过快,请稍后再试
743 time.sleep(1)
744 else:
745 print u’请求失败. StatusCode:’, rp.status_code
746
747 except Exception, e:
748 print ‘Exp {0} : {1}’.format(FuncName(), e)
749
750 return False
751
752
753 def main(options):
754 #
755 jd = JDWrapper()
756 if not jd.checkLogin():
757 if not jd.login_by_QR():
758 return
759
760 while not jd.buy(options) and options.flush:
761 time.sleep(options.wait / 1000.0)
762
763
764 if name == ‘main’:
765 # help message
766 parser = argparse.ArgumentParser(description=‘Simulate to login Jing Dong, and buy sepecified good’)
767 #parser.add_argument(’-u’, ‘–username’,
768 # help=‘Jing Dong login user name’, default=’’)
769 #parser.add_argument(’-p’, ‘–password’,
770 # help=‘Jing Dong login user password’, default=’’)
771 parser.add_argument(’-a’, ‘–area’,
772 help=‘Area string, like: 1_72_2799_0 for Beijing’, default=‘1_72_2799_0’)
773 parser.add_argument(’-g’, ‘–good’,
774 help=‘Jing Dong good ID’, default=’’)
775 parser.add_argument(’-c’, ‘–count’, type=int,
776 help=‘The count to buy’, default=1)
777 parser.add_argument(’-w’, ‘–wait’,
778 type=int, default=500,
779 help=‘Flush time interval, unit MS’)
780 parser.add_argument(’-f’, ‘–flush’,
781 action=‘store_true’,
782 help=‘Continue flash if good out of stock’)
783 parser.add_argument(’-s’, ‘–submit’,
784 action=‘store_true’,
785 help=‘Submit the order to Jing Dong’)
786
787 # example goods
788 hw_watch = ‘2567304’
789 iphone_7 = ‘3133851’
790
791 options = parser.parse_args()
792 print options
793
794 # for test
795 if options.good == ‘’:
796 options.good = iphone_7
797
798 ‘’’
799 if options.password == ‘’ or options.username == ‘’:
800 print u’请输入用户名密码’
801 exit(1)
802 ‘’’
803 main(options)