├── .gitignore ├── README.md ├── ck ├── 孙颖.txt ├── 小蓝.txt └── 沙师弟.txt ├── connect_database.py ├── coupon.txt ├── jd.py ├── jd.sql ├── requirements.txt └── 配置文件.ini /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | *.js linguist-language=Python 107 | 108 | *.css linguist-language=Python 109 | 110 | *.html linguist-language=Python 111 | 112 | *.md linguist-language=Python 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | 京东抢卷,目前只适合了解京东购物,有 Python 基础的人使用 4 | 项目源码写的虽然丑陋,但是已经应用于实践,去年618表现出色,后期会更新升级 5 | 把源码升级,使用 PyQt5 制作一个简单的可视化抢卷工具 6 | -------------------------------------------------------------------------------- /ck/孙颖.txt: -------------------------------------------------------------------------------- 1 | shshshfpb=%263AB9D23F7A4B3C9B%3D55WTDQM5H4E2UOEPGFGHCWFI47YODX2GXSJFGYLGFEVQBUXP56YHCFSGKNBDVMZABXVX3IWAJ264DZ3WZWOPG3BG2Q; shshshfp=8543a5790d32b1129a9659e79bdddd79; shshshfpa=8857e96d-6347-9890-d5cb-856c4c2e8805-1547172207; shshshsID=32e7ba7f74cd0001f037cfb85ba47eea_1_1547172207470; __jda=122270672.1547172207557826894686.1547172207.1547172207.1547172207.1; __jdb=122270672.1.1547172207557826894686|1.1547172207; __jdv=122270672|direct|-|none|-|1547172207593; __jdc=122270672; mba_muid=1547172207557826894686; mba_sid=15471722076508299017825880326.1; jcap_dvzw_fp=40fdcfb273dc42037d65bd637567b55b15471722018121657121691; TrackerID=Ayt6AIjeWLZn0eQQjhp9NR3SVlVB_Tb_mpwv226W-6xOu6gFyuRK1vuHwtiFk99UJS_zSJcNlL2EAF1IrU8EFw; pinId=n4YnKjKvbuO1ffsfn98I-w; pt_key=AAFcN_lsADDqvGBs6MX0cHWGgIMRWJct0P-KpVm6HosvARR9LLF74BOFU4SZf3sc6wxkiUs5DvU; pt_pin=SUNYC---; pt_token=agqo74a7; pwdt_id=SUNYC---; whwswswws=; SERVERID=b74190684d9ba8283cb0ac02d3afe6c2----wlfstk_smdl=mlwq9j1al6ubfz1zt12jcs49qpbg6ast; __jda=122270672.15471721919071143372822.1547172192.1547172192.1547172192.1; __jdb=122270672.2.15471721919071143372822|1.1547172192; __jdc=122270672; __jdv=122270672|direct|-|none|-|1547172191969; __jdu=15471721919071143372822; 3AB9D23F7A4B3C9B=55WTDQM5H4E2UOEPGFGHCWFI47YODX2GXSJFGYLGFEVQBUXP56YHCFSGKNBDVMZABXVX3IWAJ264DZ3WZWOPG3BG2Q; TrackID=1zVWcX5oYEifSaAkOos3PiBi2hvpwj7DVHn1QsgqCOKhhiXNwTfu4WBKIvyqg1YPvxSnGMRJmveTwI7st5aTfFQ; thor=81DCDC93ECC5F36DBCBD77642E6AED5BA10DAA38C3C60CE25423F85765383FFF8BD3272A7FC339F8E7FF0E5F372421B1DA2F1E89CDCDFFFE558D41B75804E388C32DA993C96BA8519DB01316EBFE104B970825BDB39BC321EB65294F5F9F780CB4073FDF220A16E1834742FD96748528EC35A14446DE2987E19EF313636AF4362D8D02FAC858B8581199879FA4D4C48F; pinId=n4YnKjKvbuO1ffsfn98I-w; pin=SUNYC---; unick=SUNYC---; ceshi3.com=201; _tp=NXoB80bjtXp0QD6SS6uc9w%3D%3D; logining=1; _pst=SUNYC--- -------------------------------------------------------------------------------- /ck/小蓝.txt: -------------------------------------------------------------------------------- 1 | shshshfpb=%263AB9D23F7A4B3C9B%3DTFAG3HQYQ2NAPBCNK7DYPABDXBCF7TWMBD2QFLARGNORTIAYZ5ZBHEFWAHWVX5YFA7CWDFNBKZNQMTGFEHJUVXVQ6U; shshshfp=8543a5790d32b1129a9659e79bdddd79; shshshfpa=4c112e3c-a387-a5ec-d756-f425d4760cf0-1547525272; shshshsID=9a6ef4cf223d9fb4428f7d21f1a8ac83_1_1547525272726; __jda=122270672.15475252727691854558174.1547525272.1547525272.1547525272.1; __jdb=122270672.1.15475252727691854558174|1.1547525272; __jdv=122270672|direct|-|none|-|1547525272815; __jdc=122270672; mba_muid=15475252727691854558174; mba_sid=15475252728685954891395872011.1; jcap_dvzw_fp=40fdcfb273dc42037d65bd637567b55b1547525271273972584562; TrackerID=3at-1isg-NJaTF3fpswBUts7HqguqOjlsq0dhKAgVfmb3tGYFKcY4SZ6WQC6WNFHi0wrjZ1cqK9pdEvOH6v1lDlFA_0hckn5jynxpMvEzU0; pinId=EW9jUNbxMmJPRlbVCcnTkrV9-x-f3wj7; pt_key=AAFcPVyfADAu5gSGFCVlMzH2tbNNZs3mMDniB6RsCQ7jJL9E84hjwTOpLTdz_VaR1zwDaYUc0qQ; pt_pin=jd_75bd2831ac888; pt_token=9qornch6; pwdt_id=jd_75bd2831ac888; whwswswws=; SERVERID=0af89820b31b680305a5d7783b39cbbf----wlfstk_smdl=8idp2kqdq3gwxou10tl4ypnal5pjbgnk; __jda=122270672.15475252279121195611629.1547525228.1547525228.1547525228.1; __jdb=122270672.2.15475252279121195611629|1.1547525228; __jdc=122270672; __jdv=122270672|direct|-|none|-|1547525227978; __jdu=15475252279121195611629; 3AB9D23F7A4B3C9B=TFAG3HQYQ2NAPBCNK7DYPABDXBCF7TWMBD2QFLARGNORTIAYZ5ZBHEFWAHWVX5YFA7CWDFNBKZNQMTGFEHJUVXVQ6U; TrackID=1X2oevnhQb6sflpkd-yUys3VfEHdKXmmv3ORrLXCHETQMLhRy0chwenTeqaCY3LXFYkXMbfypokT-YyPq1r7E2mlVSSg-wFNKJrnYq3WwfYA; thor=5176AE9084F0DBBEB354482A5B0EC29B1539D0CA00D5D4A1A90E0A128719F08899A344821F17CA9CD17D3D8581166D9C4B59D9D89E4BCD635305A6ED01BECB1D2138DFFD3E357BDDC82409CEB6D4A2B916FD55C6724669E14185C1DFC86F65BEA8D5FF9CE843FA80046B5EB2C272AC551CA82F5C23240F0701A41AEAA492C3DD5B08BF02A3AB4EC623EEB8BD3946A09C2E057039FF20C2BDD6DD810EE34B9E74; pinId=EW9jUNbxMmJPRlbVCcnTkrV9-x-f3wj7; pin=jd_75bd2831ac888; unick=%E6%88%91%E8%A6%81%E5%85%88%E8%B5%B0; ceshi3.com=201; _tp=s5vB0KmGSlwLECQC%2FofRXfr9TySVSXiyPGa132TvA5k%3D; logining=1; _pst=jd_75bd2831ac888 -------------------------------------------------------------------------------- /ck/沙师弟.txt: -------------------------------------------------------------------------------- 1 | shshshfp=b61c9f383b7026b483d510257a8a1b01; shshshfpa=7e9937e7-bd8a-c1b2-de83-4022ee73c295-1546230351; shshshsID=46ed4edab9e201828a721bc6fedcd762_1_1546230351705; __jda=122270672.1546230351727885776488.1546230351.1546230351.1546230351.1; __jdb=122270672.1.1546230351727885776488|1.1546230351; __jdv=122270672|direct|-|none|-|1546230351762; __jdc=122270672; mba_muid=1546230351727885776488; mba_sid=15462303518141260490090420805.1; shshshfpb=xi5NZZHWp4RwS0p9gAlqMCA%3D%3D; jcap_dvzw_fp=85f1c3fbf6ef88b7ad102ca983441b1e1546230351896971363333; TrackerID=fiyENU2jNIy841bGdmAA64QkcQtlh8QttKO4aXTQUIcjMh-fagU28-YTUevXGcPSoxHp0VlE8pvMU_RVCIuXBnXCbBjZF7_4vFywcla03Dw; pinId=WKQklT0azMuzPva8Xl69SLV9-x-f3wj7; pt_key=AAFcKZpTADDyrPNUoPuoWGZ6nO6e7QH1y0gBEoqrpbb3IAApsy1DUd6myO17Fuk4_7tNuv6r2xs; pt_pin=jd_4d2767823fef3; pt_token=4qs7xh93; pwdt_id=jd_4d2767823fef3; whwswswws=; SERVERID=c777e4ee03771b0ea2305b2acfe58b63----wlfstk_smdl=2sze83t2xkuw2o3c9xaoul1rjfrsvyty; __jda=122270672.1546230296929938391594.1546230297.1546230297.1546230297.1; __jdb=122270672.2.1546230296929938391594|1.1546230297; __jdc=122270672; __jdv=122270672|direct|-|none|-|1546230297045; __jdu=1546230296929938391594; 3AB9D23F7A4B3C9B=XHFUKWQ72LS2Q2HGYPLXCOK37LDZAN3LLWZSQINE6EEIB734M5VTGNKCNZEN6E7EI7Q3OYYUGJUD2MOYBUTICVAIJY; TrackID=1tTwaJQEw3L4Emp1IicY7DAcMawrrbPYaWxontHQeY1zpejbRHbMsq-OLUHBKE86TMH2xs2j65N6wlJN6-TbB72UNmAsBNjwXrL0-xBEkSzA; thor=EE9FFD800EDF1292F255CC539BF75FD12481355804F6CE2B7DB1E9D33A496F903DF1807EB5CBEA81484B0834CBD3F92B429F95007E678DD2BCBCB4A1AA9B87EE7AC5C4FDC4BABC1AD6526E608CE7DDF42AC4146172B928B54358ECDE6910A6C984C907729559ACA60B01F32DA8F923F6AC68FAC721B896CE8C3061BE09D916B902C16E6ED7710DE9F8788154E8CF62CBA3D18C17E394407D95000B4D96A83A51; pinId=WKQklT0azMuzPva8Xl69SLV9-x-f3wj7; pin=jd_4d2767823fef3; unick=stormsha; ceshi3.com=201; _tp=ZqBsV7VRsefFscQKFFMl2mKQXn0XdCcxxDAGR17yv5U%3D; logining=1; _pst=jd_4d2767823fef3 -------------------------------------------------------------------------------- /connect_database.py: -------------------------------------------------------------------------------- 1 | import pymysql 2 | import requests 3 | import re 4 | import time 5 | 6 | 7 | # 读取配置文件 8 | with open('./配置文件.ini', 'r', encoding='utf-8') as f: 9 | config = f.readlines() 10 | config_dict = {} 11 | 12 | for conf in config[1:]: 13 | conf = conf.split('=') 14 | config_dict[conf[0].strip()] = conf[1].strip() 15 | 16 | # 读取数据库配置信息 17 | user = config_dict['数据库账号'].strip() 18 | passwd = config_dict['数据库密码'].strip() 19 | db = config_dict['数据库名称'].strip() 20 | connect = pymysql.connect( 21 | host='localhost', 22 | user=user, 23 | passwd=passwd, 24 | db=db, 25 | charset='utf8') 26 | # 捕获异常信息 27 | try: 28 | cursor = connect.cursor() 29 | cursor.execute("truncate table jd_help") 30 | connect.commit() 31 | 32 | coupon = [] 33 | with open('coupon.txt', 'r') as f: 34 | coupons = f.readlines() 35 | for k, cou in enumerate(coupons): 36 | coupon = 'http://coupon.m.jd.com/coupons/show.action?{}&to=m.jd.com'.format(cou.strip()) 37 | res = requests.get( 38 | url=coupon, 39 | headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'} 40 | ) 41 | ur_yuan = res.content.decode('utf-8') 42 | limitStr = re.search('limitStr":"(.*?)"', ur_yuan, re.S).group(1) 43 | discount = re.search('discount":"(.*?)"', ur_yuan, re.S).group(1) 44 | quota = re.search('quota":"(.*?)"', ur_yuan, re.S).group(1) 45 | batchid = re.search('batchId":"(.*?)"', ur_yuan, re.S).group(1) 46 | batchcount = re.search('batchCount":(\d+),', ur_yuan, re.S).group(1) 47 | des = limitStr+quota+'-'+discount 48 | key = cou.split('&')[0].split('=')[1].strip() 49 | role = cou.split('&')[1].split('=')[1].strip() 50 | begintime = re.search('constraintBeginTime":"(.*?)"', ur_yuan, re.S).group(1) 51 | begintime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(int(begintime[:-3]))) 52 | endtime = re.search('constraintEndTime":"(.*?)"', ur_yuan, re.S).group(1) 53 | endtime = int(endtime[:-3]) 54 | now = int(time.time()) 55 | if now < endtime: 56 | print(k) 57 | endtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(endtime)) 58 | usetime = begintime+'----'+endtime 59 | qq = "insert into jd_help(coupon,ccount,keyid,roleid,batchid,usetime) values('{}',{},'{}','{}','{}','{}')".\ 60 | format(des, batchcount, key, role, 61 | 'https://search.jd.com/Search?https://search.jd.com/Search?coupon_batch={}'.format(batchid), usetime) 62 | cursor.execute(qq) 63 | connect.commit() 64 | except Exception as e: 65 | raise Exception(e) 66 | finally: 67 | # 关闭连接 68 | connect.close() 69 | 70 | -------------------------------------------------------------------------------- /coupon.txt: -------------------------------------------------------------------------------- 1 | key=db832e8f4e95439bb4fa0ea09b725561&roleId=17480554 -------------------------------------------------------------------------------- /jd.py: -------------------------------------------------------------------------------- 1 | import time 2 | import requests 3 | import re 4 | import os 5 | import threading 6 | import smtplib 7 | from email.mime.text import MIMEText 8 | import pymysql 9 | 10 | 11 | content = '领取结果:' 12 | status = 0 13 | resp = [] 14 | custom_url = '' 15 | 16 | # 读取配置文件 17 | with open('./配置文件.ini','r',encoding='utf-8') as f: 18 | config = f.readlines() 19 | config_dict = {} 20 | 21 | for conf in config[1:]: 22 | conf = conf.split('=') 23 | config_dict[conf[0].strip()] = conf[1].strip() 24 | 25 | # 若自定义领取链接不为空,读取领取链接 26 | if config_dict['自定义链接'] != '[]': 27 | custom_url = config_dict['自定义链接'].strip('[').strip(']') 28 | 29 | # 读取数据库优惠券信息 30 | user = config_dict['数据库账号'].strip() 31 | passwd = config_dict['数据库密码'].strip() 32 | db = config_dict['数据库名称'].strip() 33 | connect = pymysql.connect( 34 | host='localhost', 35 | user=user, 36 | passwd=passwd, 37 | db=db, 38 | charset='utf8' 39 | ) 40 | try: 41 | cursor = connect.cursor() 42 | # 读取优惠券信息 43 | cursor.execute("select * from jd_help") 44 | conf_data = cursor.fetchall() 45 | # 读取抢券接口信息 46 | cursor.execute("select port from re_port") 47 | re_port = cursor.fetchall() 48 | except Exception as e: 49 | print(e) 50 | finally: 51 | connect.close() 52 | 53 | 54 | # 读取cookie信息 55 | def get_ck(): 56 | cookie = {} 57 | ck = [] 58 | for root, dirs, files in os.walk('./ck'): 59 | for file in files: 60 | phone = file.split('.')[0] 61 | with open('./ck/'+file, 'r') as f: 62 | for i in f.readlines(): 63 | mobile = i.split('----')[0] 64 | oo = mobile.split(';') 65 | for ooo in oo: 66 | oooo = ooo.strip().split('=') 67 | cookie[oooo[0]] = oooo[1] 68 | ck.append((phone, cookie)) 69 | cookie = {} 70 | return ck 71 | 72 | 73 | # 获取京东时间 74 | def get_time(): 75 | res = requests.get( 76 | url='https://a.jd.com//ajax/queryServerData.html', 77 | headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36'}) 78 | data_server = res.json() 79 | return data_server['serverTime'] 80 | 81 | 82 | # 延续整点时间 83 | def time_pos(): 84 | t = time.localtime(int(get_time() / 1000)) 85 | if 0 <= t.tm_hour < 10: 86 | preset_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0]+' 10:00:00' 87 | elif 10 <= t.tm_hour < 12: 88 | preset_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0] + ' 12:00:00' 89 | elif 12 <= t.tm_hour < 14: 90 | preset_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0] + ' 14:00:00' 91 | elif 14 <= t.tm_hour < 16: 92 | preset_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0] + ' 16:00:00' 93 | elif 16 <= t.tm_hour < 18: 94 | preset_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0] + ' 18:00:00' 95 | elif 18 <= t.tm_hour < 20: 96 | preset_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0] + ' 20:00:00' 97 | elif 20 <= t.tm_hour < 22: 98 | preset_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0] + ' 22:00:00' 99 | else: 100 | new_year = t[0] 101 | new_month = t[1] 102 | new_day = t[2] + 1 103 | if t.tm_mon == 4 or t.tm_mon == 6 or t.tm_mon == 9 or t.tm_mon == 11: 104 | if t.tm_mday == 30: 105 | new_month = t[1] + 1 106 | new_day = '01' 107 | elif t.tm_mon == 12: 108 | if t.tm_mday == 31: 109 | new_year = t[0] + 1 110 | new_month = 1 111 | new_day = '01' 112 | elif t.tm_mon == 2: 113 | this_year = int(t.tm_year) 114 | if this_year % 400 == 0 or this_year % 4 == 0 and this_year % 100 != 0: 115 | if t.tm_mday == 29: 116 | new_month = t[1] + 1 117 | new_day = '01' 118 | else: 119 | if t.tm_mday == 28: 120 | new_month = t[1] + 1 121 | new_day = '01' 122 | else: 123 | if t.tm_mday == 31: 124 | new_month = t[1] + 1 125 | new_day = '01' 126 | preset_time = str(new_year) + '-' + str(new_month) + '-' + str(new_day) + ' 00:00:00' 127 | 128 | return preset_time 129 | 130 | 131 | # 主抢券代码 132 | def begin_get(role, key, quan_detail, phone_jiekou, begin_time, cookienum, j, oo, diff): 133 | 134 | cookies = get_ck() 135 | header = {'accept': '*/*', 136 | 'referer': 'https://wq.jd.com/activeapi/obtainjdshopfreecouponv2', 137 | 'Content-Type': 'application/x-www-form-urlencoded', 138 | 'accept-language': 'zh-cn', 139 | 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)'} 140 | oo = int(oo) 141 | # 设置开抢提前时间 142 | s = int((begin_time - oo - diff)/100)/10 143 | time.sleep(s) 144 | now = int(time.time() * 1000) 145 | swith = 0 146 | # 设置抢券循环次数 147 | for x in range(4): 148 | if swith == 1: 149 | break 150 | for url in phone_jiekou: 151 | if custom_url == '': 152 | re_url = url.format(role, now, key) 153 | else: 154 | re_url = custom_url 155 | try: 156 | jd_login = requests.get(re_url, headers=header, cookies=cookies[cookienum][1], allow_redirects=False) 157 | jds = jd_login.content.decode('utf-8') 158 | except Exception as er: 159 | print('第{}次抢卷异常'.format(x), er) 160 | continue 161 | # 判断抢券结果 162 | try: 163 | if len(jds) > 300: 164 | jds = '出了点小问题' 165 | else: 166 | jds = re.search('[\u4e00-\u9fa5]+.*[\u4e00-\u9fa5]+', jds, re.S).group() 167 | except Exception as er: 168 | print('抢卷异常', er) 169 | jds = '出了点小问题' 170 | resp.append(cookies[cookienum][0]+':'+jds) 171 | 172 | if re.search('早点来|结束|成功|重复', jds, re.S): 173 | swith = 1 174 | break 175 | if x == 0: 176 | phone_jiekou = phone_jiekou[1:] 177 | 178 | 179 | # 多线程抢券类 180 | class myThread (threading.Thread): 181 | def __init__(self, role, key, quan_detail, phone_jiekou, begintime, num, j, oo, diff): 182 | threading.Thread.__init__(self) 183 | self.begintime = begintime 184 | self.num = num 185 | self.role = role 186 | self.key = key 187 | self.quan_detail = quan_detail 188 | self.phone_jiekou = phone_jiekou 189 | self.oo = oo 190 | self.j = j 191 | self.diff = diff 192 | 193 | def run(self): 194 | """ 195 | 每个线程代表一个账户 196 | :return: 197 | """ 198 | print("任务{}:".format(self.num), self.num) 199 | begin_get(self.role, self.key, self.quan_detail, self.phone_jiekou, self.begintime, self.num, self.j, self.oo, self.diff) 200 | print("退出线程:", self.num) 201 | 202 | 203 | # 发送邮件配置 204 | def send_mail(): 205 | mail_host = config_dict['邮箱发送主机'] 206 | mail_user = config_dict['邮箱发送账号'] 207 | mail_pass = config_dict['邮箱发送密码'] 208 | sender = config_dict['邮箱发送地址'] 209 | receivers = [config_dict['邮箱接收地址']] 210 | # print(mail_host,mail_user,mail_pass,sender,receivers) 211 | title = '领券反馈' 212 | if status == 1: 213 | message = MIMEText(content, 'plain', 'utf-8') # 内容, 格式, 编码 214 | message['From'] = "{}".format(sender) 215 | message['To'] = ",".join(receivers) 216 | message['Subject'] = title 217 | try: 218 | smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 启用SSL发信, 端口一般是465 219 | smtpObj.login(mail_user, mail_pass) # 登录验证 220 | smtpObj.sendmail(sender, receivers, message.as_string()) # 发送 221 | print("已发反馈邮件") 222 | except smtplib.SMTPException as e: 223 | print(e) 224 | 225 | 226 | def run(): 227 | j = 0 228 | while True: 229 | # pc_jiekou=['http://coupon.jd.com/ilink/couponSendFront/send_index.action?key={2}da&roleId={0}&to=jd.com','https://passport.jd.com/loginservice.aspx?callback=jQuery{0}&method=Login&_={1}','https://coupon.jd.com/ilink/couponActiveFront/front_index.action?key={2}&roleId={0}&to=jd.com',] 230 | # 抢券接口信息 231 | phone_jiekou = [x[0] for x in re_port] 232 | # 获取要抢券京东账号cookie 233 | cookies = get_ck() 234 | # 读取要抢优惠券信息 235 | for p in conf_data: 236 | endtime = p[6].split('----')[1] 237 | print(p[0], p[1], endtime, p[2], p[5].split('=')[1]) 238 | # 当配置文件中自定义抢券链接为空时,使用固定接口抢券 239 | if custom_url == '': 240 | if j == 0: 241 | j = input('请输入要抢券编号:') 242 | youhuiquan = conf_data[int(j)-1] 243 | key = youhuiquan[3].strip() 244 | role = youhuiquan[4].strip() 245 | header = { 246 | 'accept': '*/*', 247 | 'referer': 'https://wq.jd.com/activeapi/obtainjdshopfreecouponv2', 248 | 'Content-Type': 'application/x-www-form-urlencoded', 249 | 'accept-language': 'zh-cn', 250 | 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)'} 251 | now = get_time() 252 | jiekou = phone_jiekou[1] 253 | urll = jiekou.format(role, now, key) 254 | # 尝试抢券获取下次开抢的准确时间 255 | jd_l = requests.get(urll, headers=header, cookies=cookies[0][1]) 256 | try: 257 | time_mec = re.search('(\d+):', jd_l.content.decode('utf-8'), re.S).group(1) 258 | yushe_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())).split(' ')[0] + ' {}:00:00'.format(time_mec) 259 | print('下场精确时间点', yushe_time) 260 | print('已开始抢券名称: ', conf_data[int(j) - 1][1], '定时时间:', yushe_time) 261 | except: 262 | print('此活动已过期') 263 | # 当准确获取开抢时间抛出异常时,自动延续下场整点时间 264 | yushe_time = time_pos() 265 | print('下场预设时间:', yushe_time) 266 | # yushe_time='2019-2-19 9:40:20' 267 | else: 268 | youhuiquan = conf_data[int(j) - 1] 269 | key = youhuiquan[3].strip() 270 | role = youhuiquan[4].strip() 271 | yushe_time = time_pos() 272 | print('当前自定义领券模式开启中', '定时时间:' + yushe_time) 273 | 274 | # 转换时间格式,并最终获取开抢unix时间戳 275 | timeArray = time.strptime(yushe_time, "%Y-%m-%d %H:%M:%S") 276 | unix = time.mktime(timeArray) 277 | unix = int(unix*1000) 278 | # 读取配置中自定义的提前开抢时间 单位为ms 279 | diff = int(config_dict['等待时间']) 280 | thread_list = [] 281 | oo = get_time() 282 | # 根据cookie数量开启多线程,建议四五个账号cookie最佳 283 | for i in range(len(cookies)): 284 | t = myThread(role, key, conf_data, phone_jiekou, unix, i, j, oo, diff) 285 | unix = unix+8 286 | thread_list.append(t) 287 | print('-------------------------------------------------') 288 | for t in thread_list: 289 | t.setDaemon(True) 290 | t.start() 291 | print('-------------------------------------------------') 292 | for t in thread_list: 293 | t.join() 294 | # check_all() 295 | global resp, content, status 296 | # 当最终领取结果中有账号领取成功时,保留当前账号的信息并添加到要发送邮箱内容文本中 297 | for res in resp: 298 | if re.search('领取成功', res, re.S): 299 | ck = res.split(':')[0] 300 | status = 1 301 | content = content + ck + youhuiquan[1] + ' ' 302 | print(res) 303 | 304 | resp = [] 305 | send_mail() 306 | status = 0 307 | content = '' 308 | print('-' * 40) 309 | 310 | 311 | if __name__ == '__main__': 312 | # 开启主函数 313 | run() 314 | send_mail() 315 | -------------------------------------------------------------------------------- /jd.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : localhost 5 | Source Server Version : 50717 6 | Source Host : localhost:3306 7 | Source Database : jd 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50717 11 | File Encoding : 65001 12 | 13 | Date: 2019-04-27 23:45:25 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for jd_help 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `jd_help`; 22 | CREATE TABLE `jd_help` ( 23 | `id` int(10) NOT NULL AUTO_INCREMENT, 24 | `coupon` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 25 | `ccount` int(100) DEFAULT NULL, 26 | `keyid` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 27 | `roleid` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 28 | `batchid` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 29 | `usetime` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 30 | PRIMARY KEY (`id`) 31 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 32 | 33 | -- ---------------------------- 34 | -- Records of jd_help 35 | -- ---------------------------- 36 | INSERT INTO `jd_help` VALUES ('1', '仅可购买海囤全球自营a2奶粉部分商品999-500', '200', '7853430d27e34edeb5c61a02c158c058', '18982121', 'https://search.jd.com/Search?https://search.jd.com/Search?coupon_batch=200902474', '2019-04-17 00:00:00----2019-04-17 23:59:59'); 37 | 38 | -- ---------------------------- 39 | -- Table structure for re_port 40 | -- ---------------------------- 41 | DROP TABLE IF EXISTS `re_port`; 42 | CREATE TABLE `re_port` ( 43 | `id` tinyint(10) NOT NULL AUTO_INCREMENT, 44 | `port` varchar(300) COLLATE utf8mb4_unicode_ci NOT NULL, 45 | PRIMARY KEY (`id`) 46 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 47 | 48 | -- ---------------------------- 49 | -- Records of re_port 50 | -- ---------------------------- 51 | INSERT INTO `re_port` VALUES ('1', 'https://plus.m.jd.com/coupon/receiveCoupon?activeKey={2}&roleId={0}'); 52 | INSERT INTO `re_port` VALUES ('2', 'https://api.m.jd.com/client.action?functionId=newBabelAwardCollection&body={{%22activityId%22:%2225N4bVkmMV4S2RL61A8DYNwqD8Vv%22,%22from%22:%22H5node%22,%22scene%22:%221%22,%22args%22:%22key={2},roleId={0}%22}}&client=wh5&clientVersion=1.0.0&callback=jsonp2'); 53 | INSERT INTO `re_port` VALUES ('3', 'https://act-jshop.jd.com/couponSend.html?callback=jQuery5047673&ruleId={0}&key={2}&platform=0'); 54 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2019.3.9 2 | chardet==3.0.4 3 | idna==2.8 4 | PyMySQL==0.9.3 5 | requests==2.21.0 6 | urllib3==1.24.2 7 | -------------------------------------------------------------------------------- /配置文件.ini: -------------------------------------------------------------------------------- 1 | [配置选项] 2 | 网络延迟=100 3 | 等待时间=1355 4 | 邮箱发送主机 = smtp.163.com 5 | 邮箱发送账号 = 6 | 邮箱发送密码 = 7 | 邮箱发送地址 = 8 | 邮箱接收地址 = 9 | 自定义链接=[] 10 | 数据库账号=root 11 | 数据库密码=root 12 | 数据库名称=jd --------------------------------------------------------------------------------