Python爬虫,京东自动登录,在线抢购商品

时间:2019-10-20
本文章向大家介绍Python爬虫,京东自动登录,在线抢购商品,主要包括Python爬虫,京东自动登录,在线抢购商品使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

京东抢购
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

ps:推荐一下我建的python零基础系统学习交流扣扣qun:前面是934,中间109,后面是170,群里有免费的视频教程,开发工具、电子书籍分享。专业的老师答疑!学习python web、python爬虫、数据分析、大数据,人工智能等技术有不懂的可以加入一起交流学习,一起进步!

项目源码分享

  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(r):
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)

原文地址:https://www.cnblogs.com/xiaoyiq/p/11706757.html