├── nike.db
├── README.md
├── nike.db
├── .idea
├── vcs.xml
├── misc.xml
├── modules.xml
├── snkrs.iml
└── workspace.xml
├── main2.py
├── .gitignore
├── WebLoginnk.py
├── snkrs.py
├── main.py
└── loginnk.py
/ nike.db:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # snkrsbot
2 | snkrs多线程抢购
3 |
--------------------------------------------------------------------------------
/nike.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/13476075014/snkrsbot/HEAD/nike.db
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/snkrs.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/main2.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | from loginnk import *
3 | import re
4 | import requests
5 | from WebLoginnk import *
6 | import threading,sqlite3,time
7 | from multiprocessing import Process
8 | from multiprocessing import Queue
9 |
10 | def partdraw(chouqian):
11 |
12 | print("nihao")
13 | conn = sqlite3.connect("nike.db")
14 | conn.text_factory = str
15 | c = conn.cursor()
16 | allUser = c.execute("SELECT * from nike").fetchall()
17 | for user in allUser:
18 | username = user[2]
19 | password = user[3]
20 | refreshToken = user[1]
21 | # print("%s %s %s",username,password,refreshToken)
22 | #参与抽签
23 | partdraw()
24 | c.close()
25 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/WebLoginnk.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import json
3 | import random
4 | import traceback
5 | import requests
6 | from selenium import webdriver
7 | from selenium.webdriver import ActionChains
8 | from selenium.webdriver.support.wait import WebDriverWait
9 |
10 |
11 | class WebLogin_Chrome:
12 | def __init__(self, username, password):
13 | self.cookies = None
14 | self.session = requests.session()
15 | self.userInfo = None
16 |
17 | self.username = username
18 | self.password = password
19 |
20 | def login(self):
21 | try:
22 | chromeOptions = webdriver.ChromeOptions()
23 | # 无界面
24 | # chromeOptions.add_argument('--headless')
25 | # 禁用gpu加速
26 | chromeOptions.add_argument('--disable-gpu')
27 | # 关闭图片
28 | prefs = {"profile.managed_default_content_settings.images": 2}
29 | chromeOptions.add_experimental_option("prefs", prefs)
30 |
31 | driver = webdriver.Chrome(chrome_options=chromeOptions)
32 |
33 | w_h = driver.get_window_size()
34 | width = w_h["width"]
35 | height = w_h["height"]
36 |
37 | clickWidth1 = (width - 500) / 2
38 | clickWidth2 = width / 2 + 250
39 |
40 | driver.get("https://www.nike.com/cn/zh_cn/")
41 | WebDriverWait(driver, 15).until(lambda x: x.find_element_by_class_name('login-text'))
42 | driver.find_element_by_class_name('login-text').click()
43 |
44 | # 随机位置点击绕过验证
45 | for i in range(random.randint(2, 5)):
46 | ActionChains(driver).move_by_offset(clickWidth1,
47 | random.randint(0, height)).click().perform()
48 | ActionChains(driver).move_by_offset(clickWidth2,
49 | random.randint(0, height)).click().perform()
50 |
51 | driver.find_element_by_name('verifyMobileNumber').send_keys(self.username)
52 | driver.find_element_by_name('password').send_keys(self.password)
53 | driver.find_element_by_class_name('nike-unite-submit-button').click()
54 |
55 | # 随机位置点击绕过验证
56 | for i in range(random.randint(2, 5)):
57 | ActionChains(driver).move_by_offset(clickWidth1,
58 | random.randint(0, height)).click().perform()
59 | ActionChains(driver).move_by_offset(clickWidth2,
60 | random.randint(0, height)).click().perform()
61 | try:
62 | WebDriverWait(driver, 5).until_not(
63 | lambda x: x.find_element_by_class_name('exp-join-login').is_displayed())
64 | except:
65 | # print("等待超时...")
66 | pass
67 | if not driver.find_element_by_xpath('//*[@id="nike-unite-mobileLoginForm"]/div[1]').is_displayed():
68 | WebDriverWait(driver, 10).until_not(
69 | lambda x: x.find_element_by_class_name('exp-join-login').is_displayed())
70 |
71 | self.cookies = driver.get_cookies()
72 |
73 | driver.get("https://unite.nike.com/session.html")
74 | userInfo = driver.execute_script(
75 | "return localStorage.getItem('com.nike.commerce.nikedotcom.web.credential');")
76 | self.userInfo = json.loads(userInfo)
77 | except:
78 | traceback.print_exc()
79 | finally:
80 | driver.close()
81 | driver.quit()
82 |
83 | def getCookies(self):
84 | cookies = ""
85 | if self.cookies != None:
86 | for cookie in self.cookies:
87 | cookies += (cookie['name'] + "=" + cookie['value'] + ";")
88 | return cookies
--------------------------------------------------------------------------------
/snkrs.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import requests,time,json
3 | from selenium import webdriver
4 |
5 | chromeOptions = webdriver.ChromeOptions()
6 | #无界面
7 | #chromeOptions.add_argument('--headless')
8 | #关闭图片
9 | prefs = {"profile.managed_default_content_settings.images": 2}
10 | chromeOptions.add_experimental_option("prefs", prefs)
11 | #禁用gpu加速
12 | chromeOptions.add_argument('--disable-gpu')
13 | browser=webdriver.Chrome(chrome_options=chromeOptions)
14 |
15 | browser.get("https://www.nike.com/cn/zh_cn/")
16 | login=browser.find_element_by_class_name("login-text")
17 | login.click()
18 | login1=browser.find_elements_by_tag_name("a")
19 | login1[264].click()
20 | username=browser.find_element_by_name("emailAddress")
21 | username.send_keys("lktop@vip.qq.com")
22 | password=browser.find_element_by_name("password")
23 | password.send_keys("huanxiangmf1Q")
24 | loginbu=browser.find_elements_by_tag_name("input")
25 | loginbu[7].click()
26 | time.sleep(5)
27 | acookies = browser.get_cookies()
28 | cookie=""
29 | if acookies != None:
30 | for i in acookies:
31 | cookie += (i['name'] + "=" + i['value'] + ";")
32 | #print cookie
33 | head={
34 | "accept":"*/*",
35 | "accept-encoding": "gzip, deflate, br",
36 | "accept-language": "zh-CN,zh;q=0.9",
37 | "cache-control": "no-cache",
38 | "cookie": '''AnalysisUserId=183.60.197.103.103401539491276992; anonymousId=7BE12371D7FF8715B6B0BD9D408C75CE; guidU=a6e97f21-5101-459e-adf7-e585e219da0d; neo.swimlane=45; cicPWIntercept=1; _gcl_au=1.1.1525637876.1539491304; ajs_user_id=null; ajs_group_id=null; ajs_anonymous_id=%227BE12371D7FF8715B6B0BD9D408C75CE%22; CONSUMERCHOICE_SESSION=t; RES_TRACKINGID=777245231343142; ResonanceSegment=1; _gscu_207448657=394913175rv8lz17; _smt_uid=5bc2c5f5.4e697c8b; lls=3; siteCatalyst_sample=79; dreamcatcher_sample=19; neo_sample=53; NIKE_CART=b:c; NIKE_COMMERCE_COUNTRY=CN; NIKE_COMMERCE_LANG_LOCALE=zh_CN; CONSUMERCHOICE=cn/zh_cn; cicIntercept=1; neo.experiments=%7B%22main%22%3A%7B%223333-interceptor-cn%22%3A%22a%22%2C%220001%22%3A%22a%22%7D%2C%22thirdparty%22%3A%7B%7D%2C%22snkrs%22%3A%7B%7D%2C%22ocp%22%3A%7B%7D%7D; dreams_sample=81; DAPROPS="sdevicePixelRatio:1|sdeviceAspectRatio:16/9|bcookieSupport:1"; Hm_lvt_ed406c6497cc3917d06fd572612b4bba=1541683422; _qzja=1.1540173633.1541683422347.1541683422347.1541683422347.1541683432979.1541683432989..0.0.5.1; _abck=B8713214F31DF576A68BE3559AA55356~0~YAAQZCCEtv3oRNRmAQAA12Z+8wA1hKH/hKkH/aWS5uiD9vQK7fTMBGtJolG9lWI2X/zmxA5eCMXJRHvtWU5nJCtIImlL+fI3e6M+mQOQ4tY/Un7VOL/bhNiKzu5GKPrEASi3mOXVN4KklzIHu96JWy8mWB2uC8pAaBmWHD+3ByQV0eVV6ytzPLpWUXpyJYenk/jZzTbSmhVRYLxTJk3CAzQ2bxRl9C32zVChw4dVr7Cun6UWrFNAapvi4a8/haYUAKGyLGBsE8mHMooCsqa5NZEpPQ+WwGtRBcNjxLdOgshDryU55ZOn~-1~-1~-1; guidS=2e3cc0e5-50d7-48eb-d25d-e9c6c470fb60; guidSTimestamp=1541738243660|1541738447570; slCheck=p3R8AIZyGAY7sAexQaSJunIzfRoO6K5Ikpxtb/VQzdf3hLCKiK5PcS2ry12OQUL5LemYkFAUOM+ji1VpQLgNM7hIvEq6OMyEjH5v1u+wcaBKdV3S1ix0bDwu4Rj4KQxi; llCheck=ldrPb4mb57cawquFbnCVqtixTR/Wg/sHvJquFPTX6FAOVQUzkoEcExAJ3ZckFnLiUFFDAyUp0UQMGdUm6Avrupr0srhhYy9fYfpsRFccGhV+gBug5rUbYnyY1Yysz9/t/LAvxcNylGXQbo+RKPMg9OBDxsTITFcCc5d9kdBw8Ww=; bm_sz=92BB9CA0B2E244F7604A25B55720F54E~QAAQxPLzPy3rzdJmAQAAZOSN+A+OJESmuKu62THFSHWbZBTYTWSRNERhJwuhSvWExBXB9xCiXDSoRr8tYQlZzzZpJVDW8OBcrgrWl6CeV3M4Vo+XiHzD6Czbdsku41wFDDolvLTytI/UV2MEAwkI7n/AwtwPxdhUrFOHVrlJi8Oc9NFG1f+j9uCGgpPk; ak_bmsc=B30A0C36228384015D971BA8262590CDB73CC567865500008685E55BFF6D4E65~pl4mrzyOo/LOsTaYhqWemib8HzeuwcplVP2DgjLArOUdbyr9FdHjUEoO5F14OKMkrrjgNgjvX7/3tyEFWRHypxF3AYFNXQe83KuzSeasvdHQcmKNPakWQaxUDZtOj443ilwUnCxk2FQijIop8Y5+cf3ZdgBZjOrvBg+8AhAVp0DDxUTsWcXk+W82d0rYLjsXgVz4MOfUjMnNIdCb4nFxkHt7KALAbZwze13up4ih0RtteGDRTt0YomPvUjxYw3yZ+J3XMIoMsstlxdgzExpDlXvEAwZLUVgDrkP0wC4FLLH7hZmFWi7piphD0KS9BIWqBNPdwcN22P8jJ9kIIelqKWSQ==; mm_wc_pmt=1; _gscbrs_207448657=1; AMCVS_F0935E09512D2C270A490D4D%40AdobeOrg=1; AMCV_F0935E09512D2C270A490D4D%40AdobeOrg=690614123%7CMCIDTS%7C17845%7CMCMID%7C81273656479516255450967188602063724350%7CMCAAMLH-1542373508%7C11%7CMCAAMB-1542373508%7CRKhpRz8krg2tLO6pguXWp5olkAcUniQYPHaMWWgdJ3xzPWQmdj0y%7CMCOPTOUT-1541775908s%7CNONE%7CMCAID%7CNONE%7CvVersion%7C3.1.0; APID=C7DF1D25802F715CFC07EA0268F217F9.sin-333-app-ap-0; sls=1; CART_SUMMARY=%7B%22profileId%22+%3A%2218571452869%22%2C%22userType%22+%3A%22DEFAULT_USER%22%2C%22securityStatus%22+%3A%221%22%2C%22cartCount%22+%3A0%7D; exp.swoosh.user=%7B%22granted%22%3A0%7D; RES_SESSIONID=173321429392054; ppd=homepage%7Cnikecom%3Ehomepage; utag_main=_st:1541770728072$ses_id:1541769412741%3Bexp-session; NIKE_CART_SESSION={%22bucket%22:%22jcart%22%2C%22country%22:%22CN%22%2C%22id%22:0%2C%22merged%22:false}; _gscs_207448657=41768707r37jpz19|pv:3; s_sess=%20c51%3Dhorizontal%3B%20prevList2%3D%3B%20s_cc%3Dtrue%3B%20tp%3D6122%3B%20s_ppv%3Dunified%252520profile%25253Elogin%252C15%252C15%252C947%3B; RT="sl=3&ss=1541768585969&tt=46230&obo=0&sh=1541768938553%3D3%3A0%3A46230%2C1541768922014%3D2%3A0%3A30002%2C1541768707214%3D1%3A0%3A4895&dm=nike.com&si=c7430edb-3a32-4e45-9f0f-da5df251b30a&bcn=%2F%2F17d98a5e.akstat.io%2F&ld=1541768938554&nu=https%3A%2F%2Fwww.nike.com%2Fcn%2Fzh_ch%2Fc%2Fnike-plus&cl=1541769101970&r=https%3A%2F%2Fwww.nike.com%2Fcn%2Fzh_cn%2F&ul=1541769101982&hd=1541769129944"; nike_locale=cn/zh_cn; bm_sv=86BA91B8A14E3ED6A91A03AB2314EED9~g5KC366LXL4lHnJyGJ8KXHvJ5zRyuIj1b2NsXu3JKAJJCvHCsaYhfxxeNAZrLjXZdqRF2MI6BZT1uD0ClpMQED9Swxl9ruus63OJfIqIqYXkz8dIpGNbfR9WJu1vJUSUpH86kAoD9mdxwdvIY1oDnMRNn8Pt3SSa6boOxsk76gc=; s_pers=%20c58%3Dno%2520value%7C1541770900873%3B%20s_dfa%3Dnikecomprod%7C1541770973836%3B''',
39 | "pragma": "no-cache",
40 | "referer": "https://www.nike.com/cn/zh_cn/e/nike-plus-membership",
41 | "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36",
42 | }
43 | x=requests.get("https://www.nike.com/cn/zh_cn/e/nike-plus-membership",headers=head)
44 | print x.content
45 | #print(browser.page_source)
46 | time.sleep(10)
47 | #browser.close()
48 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | from loginnk import *
3 | import re
4 | import requests
5 | from WebLoginnk import *
6 | import threading,sqlite3,time
7 | from multiprocessing import Process
8 | from multiprocessing import Queue
9 |
10 |
11 |
12 | def getPostpayLink(productId, shoesLink):
13 | url = "https://api.nike.com/merch/products/v2/" + productId
14 | response = requests.get(url).json()
15 | postpayLink = shoesLink + "?LEStyleColor={styleColor}&LEPaymentType=Alipay".format(
16 | styleColor=response["styleColor"])
17 | return postpayLink
18 |
19 |
20 | def buySet(shoesUrl):
21 | response = requests.get(shoesUrl).text
22 |
23 | launchId = re.findall(r"\"launchViewId\":\"(.*?)\"", response, re.S | re.I)[0]
24 | size = re.findall(r"\"sizes\":(.*?),\"_fetchedAt\"", response, re.S | re.I)[0]
25 | productId = re.findall(r"product\":{\"productId\":\"(.*?)\"", response, re.S | re.I)[0]
26 |
27 | shoesLink = re.findall(r"canonical\" href=\"(.*?)\"", response, re.S | re.I)[0]
28 | postpayLink = getPostpayLink(productId, shoesLink)
29 |
30 | stock = []
31 | outOfStock = []
32 |
33 | j_size = json.loads(size)
34 |
35 | for s in j_size:
36 | if j_size[s]["available"]:
37 | stock.append(j_size[s]["localizedSize"])
38 | else:
39 | outOfStock.append(j_size[s]["localizedSize"])
40 | stock.sort()
41 | outOfStock.sort()
42 |
43 | if len(outOfStock) > 0:
44 | print(" ".join(outOfStock) + "尺码缺货\n请选择" + " ".join(stock))
45 | else:
46 | print("所有尺码有货\n请选择" + " ".join(stock))
47 |
48 | shoesSize = input("-->")
49 |
50 | for s in j_size:
51 | if j_size[s]["localizedSize"] == shoesSize:
52 | usShoesSize = s
53 | skuId = j_size[s]["skuId"]
54 |
55 | # print("请设置好默认收货地址")
56 |
57 | # print("请选择支付方式 1.银联 2.微信 3.支付宝")
58 | # purMethod = input("-->")
59 |
60 | # shoesBuyUrl = shoesUrl + "/?productId=" + launchId + "&size=" + usShoesSize
61 |
62 | return shoesSize, launchId, skuId, productId, postpayLink
63 |
64 | if __name__ == '__main__':
65 | shoesSize, launchId, skuId, productId, postpayLink = buySet(
66 | "https://www.nike.com/cn/launch/t/air-max-270-volt-black-oil-grey/")
67 |
68 | threads = int(input("根据参与用户数量自行设置一个购买和监控的线程数:"))
69 |
70 | userInfoList = []
71 |
72 |
73 | def bulkPurchase(orderQueue):
74 | def buy(refreshToken, username, password):
75 | try:
76 | app = BuySnkrs(refreshToken, skuId, launchId, productId, postpayLink)
77 |
78 | setShippingOptionsIdResponse = app.setShippingOptionsId()
79 | # print(setShippingOptionsIdResponse)
80 |
81 | setCheckoutIdResponse = app.setCheckoutId()
82 | # print(setCheckoutIdResponse)
83 |
84 | totalPrice, priceChecksum = app.getPriceChecksum()
85 | # print(totalPrice, priceChecksum)
86 |
87 | paymentToken = app.getPaymentToken(totalPrice)
88 | # print(paymentToken)
89 |
90 | launchEntrie = app.launchEntrie(paymentToken, priceChecksum)
91 | userInfo = [refreshToken, launchEntrie["id"], username, password]
92 | orderQueue.put(userInfo)
93 | except:
94 | traceback.print_exc()
95 | finally:
96 | td.release()
97 |
98 | conn = sqlite3.connect("nike.db")
99 | conn.text_factory = str
100 | c = conn.cursor()
101 | allUser = c.execute("SELECT * from nike").fetchall()
102 |
103 | td = threading.BoundedSemaphore(threads)
104 | threadlist = []
105 | for user in allUser:
106 | username = user[2]
107 | password = user[3]
108 | refreshToken = user[1]
109 | #print("%s %s %s",username,password,refreshToken)
110 | td.acquire()
111 | t = threading.Thread(target=buy, args=(refreshToken, username, password))
112 | t.start()
113 | threadlist.append(t)
114 | for x in threadlist:
115 | x.join()
116 |
117 | c.close()
118 |
119 |
120 | def orderStatus(orderQueue):
121 | def checkStatus(u):
122 | try:
123 | token, order, usr, pwd = u
124 | url = "https://unite.nikecloud.com/tokenRefresh?backendEnvironment=identity&locale=zh_CN&mobile=true&native=true&uxId=com.nike.commerce.snkrs.ios&sdkVersion=2.8.4&backendEnvironment=identity&platform=ios&browser=uniteSDK"
125 | data = {"client_id": "G64vA0b95ZruUtGk1K0FkAgaO3Ch30sj", "grant_type": "refresh_token",
126 | "refresh_token": token}
127 | r = requests.post(url, json=data).json()
128 | accessToken = r["access_token"]
129 | headers = {"authorization": "Bearer " + accessToken}
130 | response = requests.get("https://api.nike.com/launch/entries/v2/" + order, headers=headers).json()
131 | print(usr, response)
132 | try:
133 | result = response["result"]
134 | except:
135 | return
136 | if result["status"] == "WINNER":
137 | print("抢购成功, 帐号:%s 密码:%s (自行登陆手机app可查看订单)" % (usr, pwd))
138 | userInfoList.remove(u)
139 | elif result["status"] == "NON_WINNER":
140 | print("%s 抢购失败" % usr)
141 | userInfoList.remove(u)
142 | except:
143 | traceback.print_exc()
144 | finally:
145 | td.release()
146 |
147 | while True:
148 | if not orderQueue.empty():
149 | userInfo = orderQueue.get(True)
150 | userInfoList.append(userInfo)
151 | else:
152 | if len(userInfoList) != 0:
153 | td = threading.BoundedSemaphore(threads)
154 | threadlist = []
155 | for u in userInfoList:
156 | td.acquire()
157 | t = threading.Thread(target=checkStatus, args=(u,))
158 | t.start()
159 | threadlist.append(t)
160 | for x in threadlist:
161 | x.join()
162 | else:
163 | time.sleep(2)
164 |
165 |
166 | orderQueue = Queue()
167 | #buy = Process(target=bulkPurchase, args=(orderQueue,))
168 | #status = Process(target=orderStatus, args=(orderQueue,))
169 | #buy.start()
170 | #status.start()
171 | bulkPurchase(Queue())
172 | orderStatus(Queue())
--------------------------------------------------------------------------------
/loginnk.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import json
3 | import socket
4 | import ssl
5 | import traceback,time
6 | import uuid
7 | import requests
8 | from WebLoginnk import WebLogin_Chrome
9 |
10 |
11 |
12 | class LoginInit:
13 | def __init__(self, username, password):
14 | self.username = "+86" + username
15 | self.password = password
16 |
17 | self.host = "s3.nikecdn.com"
18 | self.visitorId = str(uuid.uuid4())
19 | self.clientId = "G64vA0b95ZruUtGk1K0FkAgaO3Ch30sj"
20 | self.userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79"
21 |
22 | webLogin = WebLogin_Chrome(username, password)
23 | webLogin.login()
24 | self.cookies = webLogin.getCookies()
25 |
26 | # 获取app登陆请求
27 | def getLoginRequests(self):
28 | payload = '{{"username":"{usr}","password":"{pwd}","client_id":"{clientId}","ux_id":"com.nike.commerce.snkrs.ios","grant_type":"password"}}'.format(
29 | usr=self.username, pwd=self.password, clientId=self.clientId)
30 |
31 | head = '''POST /login?appVersion=454&experienceVersion=375&uxid=com.nike.commerce.snkrs.ios&locale=zh_CN&backendEnvironment=identity&browser=Apple%20Computer%2C%20Inc.&os=undefined&mobile=true&native=true&visit=1&visitor={visitorId} HTTP/1.1
32 | Host: {host}
33 | Content-Type: application/json
34 | Origin: https://{host}
35 | Cookie: {cookies}
36 | Content-Length: {length}
37 | Connection: close
38 | Accept: */*
39 | User-Agent: {userAgent}
40 | Referer: https://s3.nikecdn.com/unite/mobile.html?mid=66794190406425515927935901233201301138?iOSSDKVersion=2.8.4&clientId=G64vA0b95ZruUtGk1K0FkAgaO3Ch30sj&uxId=com.nike.commerce.snkrs.ios&view=none&locale=zh_CN&backendEnvironment=identity
41 | Accept-Language: zh-cn'''.format(visitorId=self.visitorId, host=self.host, userAgent=self.userAgent,
42 | length=len(payload), cookies=self.cookies)
43 |
44 | data = head + "\r\n\r\n" + payload
45 | return data
46 |
47 | def getDataFromResponse(self, data):
48 | data = json.loads(data.split("\r\n\r\n")[1])
49 | return data
50 |
51 | # 发送请求
52 | def sendRequestsToHost(self, data):
53 | sock = ssl.wrap_socket(socket.socket())
54 | sock.connect((self.host, 443))
55 |
56 | sock.sendall(bytes(data, encoding='utf-8'))
57 | # recv_data = sock.recv(10240).decode('utf-8')
58 | result = ""
59 | while True:
60 | try:
61 | recv_data = sock.recv(2048)
62 | result += recv_data.decode('utf-8')
63 | except socket.error as err_msg:
64 | print('Error receiving data: %s' % err_msg)
65 | if not len(recv_data):
66 | break
67 | sock.close()
68 | return result
69 |
70 | #ceshi=LoginInit('15245871026','huanxiangmf1Q')
71 | #print (ceshi.sendRequestsToHost(data=ceshi.getLoginRequests()))
72 |
73 | class BuySnkrs:
74 | def __init__(self, refreshToken, skuId, launchId, productId, postpayLink):
75 | self.refreshToken = refreshToken
76 |
77 | self.skuId = skuId
78 | self.launchId = launchId
79 | self.productId = productId
80 | self.postpayLink = postpayLink
81 |
82 | self.host = "s3.nikecdn.com"
83 | self.apiHost = "api.nike.com"
84 | self.visitorId = str(uuid.uuid4())
85 | self.clientId = "G64vA0b95ZruUtGk1K0FkAgaO3Ch30sj"
86 | self.userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79"
87 |
88 | self.apiUserAgent = "SNKRS/3.3.3 (iPhone; iOS 11.4; Scale/2.00)"
89 | self.xNewRelicID = "VQYGVF5SCBADUVBRBgAGVg=="
90 | self.xNikeCallerId = "nike:snkrs:ios:3.3"
91 |
92 | self.checkoutId = str(uuid.uuid4())
93 | self.shippingId = str(uuid.uuid4())
94 | self.paymentsId = str(uuid.uuid4())
95 |
96 | self.times = self.getUtcTime()
97 |
98 | self.token = self.getTokenRefresh()
99 |
100 | # 格式化一些购买过程中所需的参数
101 | self.userCommerce = self.getUserCommerce()
102 | self.email = self.userCommerce["emails"]["primary"]["email"]
103 |
104 | # print(self.userCommerce["address"])
105 | # for i in self.userCommerce["address"]:
106 | # address = self.userCommerce["address"][i]
107 | # break
108 | address = self.userCommerce["address"]["shipping"]
109 | state = address["province"]
110 | city = address["locality"]
111 | county = address["zone"]
112 | address1 = address["line1"]
113 | try:
114 | address2 = address["line2"]
115 | except:
116 | address2 = " "
117 | postalCode = address["code"]
118 | country = address["country"]
119 | self.addressInfo = {"state": state, "city": city, "address1": address1, "postalCode": postalCode,
120 | "address2": address2, "county": county, "country": country}
121 |
122 | name = address["name"]["primary"]
123 | lastName = name["given"]
124 | firstName = name["family"]
125 | self.recipientInfo = {"lastName": lastName, "firstName": firstName}
126 |
127 | phone = address["phone"]["primary"]
128 | self.contactInfo = {"phoneNumber": phone, "email": self.email}
129 |
130 | # 格式化最终抢购所需的参数
131 | self.launchRecipient = {"lastName": lastName, "firstName": firstName, "email": self.email,
132 | "phoneNumber": phone}
133 |
134 | self.launchAddress = {"state": state, "city": city, "address1": address1, "county": county, "country": "CN"}
135 |
136 | # 获取服务器时区的时间
137 | def getUtcTime(self):
138 | utcTime = time.gmtime()
139 | return utcTime
140 |
141 | # 获取最新发布的产品
142 | def gwtProductFeed(self):
143 | response = requests.get(
144 | "https://api.nike.com/commerce/productfeed/products/snkrs/threads?country=CN&limit=5&locale=zh_CN&skip=0&withCards=true").json()
145 | return response
146 |
147 | # 获取新的通知信息
148 | def getNotifications(self):
149 | times = time.strftime("%Y-%m-%dT%H%%3A%M%%3A%S.000%%2B0000", self.times)
150 | url = "https://api.nike.com/plus/v3/notifications/me/stored?since={time}&limit=10&locale=zh-Hans_CN".format(
151 | time=times)
152 | headers = {
153 | "deliveryId": "com.nike.onenikecommerce",
154 | "appid": "com.nike.commerce.snkrs.ios",
155 | "Authorization": "Bearer " + self.token,
156 | "User-Agent": self.apiUserAgent,
157 | "X-NewRelic-ID": self.xNewRelicID
158 | }
159 | response = requests.get(url, headers=headers).json()
160 | return response
161 |
162 | # 获取订单信息
163 | def getOrderHistory(self):
164 | url = "https://api.nike.com/commerce/ap/orderhistory?action=getOrderHistoryList&country=CN"
165 | headers = {
166 | "X-NewRelic-ID": self.xNewRelicID,
167 | "User-Agent": self.apiUserAgent,
168 | "Authorization": "Bearer " + self.token
169 | }
170 | response = requests.get(url, headers=headers).text
171 | return response
172 |
173 | # 刷新登陆凭证
174 | def getTokenRefresh(self):
175 | url = "https://unite.nikecloud.com/tokenRefresh?backendEnvironment=identity&locale=zh_CN&mobile=true&native=true&uxId=com.nike.commerce.snkrs.ios&sdkVersion=2.8.4&backendEnvironment=identity&platform=ios&browser=uniteSDK"
176 | data = {"client_id": self.clientId, "grant_type": "refresh_token",
177 | "refresh_token": self.refreshToken}
178 | r = requests.post(url, json=data).json()
179 | return r["access_token"]
180 |
181 | # 获取用户基本信息
182 | def getUserCommerce(self):
183 | url = "https://api.nike.com/user/commerce"
184 | headers = {
185 | "X-NewRelic-ID": self.xNewRelicID,
186 | "User-Agent": self.apiUserAgent,
187 | "Authorization": "Bearer " + self.token,
188 | "X-NIKE-UX-ID": "com.nike.commerce.snkrs.ios"
189 | }
190 | response = requests.get(url, headers=headers).json()
191 | return response
192 |
193 | def setShippingOptionsId(self):
194 | url = "https://api.nike.com/buy/shipping_options/v2"
195 | headers = {
196 | "Accept": "application/json",
197 | "Authorization": "Bearer " + self.token,
198 | "Content-Type": "application/json; charset=utf-8",
199 | "x-nike-caller-id": self.xNikeCallerId,
200 | "User-Agent": self.apiUserAgent,
201 | "X-NewRelic-ID": self.xNewRelicID
202 | }
203 | data = {"items": [{"id": self.shippingId, "shippingAddress": self.addressInfo, "skuId": self.skuId}],
204 | "currency": "CNY", "country": "CN"}
205 | response = requests.post(url, headers=headers, json=data).json()
206 | return response
207 |
208 | def setCheckoutId(self):
209 | url = "https://api.nike.com/buy/checkout_previews/v2/" + self.checkoutId
210 | headers = {
211 | "Accept": "application/json",
212 | "Authorization": "Bearer " + self.token,
213 | "Content-Type": "application/json",
214 | "x-nike-caller-id": self.xNikeCallerId,
215 | "User-Agent": self.apiUserAgent,
216 | "X-NewRelic-ID": self.xNewRelicID
217 | }
218 | data = {"request": {"email": self.email,
219 | "clientInfo": {"deviceId": "", "client": "com.nike.commerce.snkrs.ios"}, "currency": "CNY",
220 | "items": [{"recipient": self.recipientInfo,
221 | "shippingAddress": self.addressInfo,
222 | "id": self.shippingId, "quantity": 1,
223 | "skuId": self.skuId,
224 | "shippingMethod": "GROUND_SERVICE",
225 | "contactInfo": self.contactInfo}],
226 | "channel": "SNKRS", "locale": "zh_CN", "country": "CN"}}
227 | response = requests.put(url, headers=headers, json=data).json()
228 | return response
229 |
230 | def getPriceChecksum(self):
231 | url = "https://api.nike.com/buy/checkout_previews/v2/jobs/" + self.checkoutId
232 | headers = {
233 | "Accept": "application/json",
234 | "X-NewRelic-ID": self.xNewRelicID,
235 | "x-nike-caller-id": self.xNikeCallerId,
236 | "Authorization": "Bearer " + self.token,
237 | "User-Agent": self.apiUserAgent
238 | }
239 | response = requests.get(url, headers=headers).json()
240 | totalPrice = response["response"]["totals"]["total"]
241 | priceChecksum = response["response"]["priceChecksum"]
242 | return totalPrice, priceChecksum
243 |
244 | def getPaymentToken(self, totalPrice):
245 | url = "https://api.nike.com/payment/preview/v2"
246 | headers = {
247 | "Accept": "application/json; charset=utf-8",
248 | "Authorization": "Bearer " + self.token,
249 | "Content-Type": "application/json",
250 | "x-nike-caller-id": self.xNikeCallerId,
251 | "User-Agent": self.apiUserAgent,
252 | "X-NewRelic-ID": self.xNewRelicID
253 | }
254 | data = {"total": totalPrice, "items": [{"productId": self.productId,
255 | "shippingAddress": self.addressInfo}],
256 | "checkoutId": self.checkoutId, "currency": "CNY", "paymentInfo": [
257 | {"id": self.paymentsId, "type": "Alipay",
258 | "billingInfo": {"name": self.recipientInfo,
259 | "contactInfo": self.contactInfo,
260 | "address": self.addressInfo}}], "country": "CN"}
261 | response = requests.post(url, headers=headers, json=data).json()
262 | paymentToken = response["id"]
263 | return paymentToken
264 |
265 | def getDataFromResponse(self, data):
266 | data = json.loads(data.split("\r\n\r\n")[1])
267 | return data
268 |
269 | # 发送请求
270 | def sendRequestsToHost(self, data):
271 | sock = ssl.wrap_socket(socket.socket())
272 | sock.connect((self.host, 443))
273 |
274 | sock.sendall(bytes(data, encoding='utf-8'))
275 | # recv_data = sock.recv(10240).decode('utf-8')
276 | result = ""
277 | while True:
278 | try:
279 | recv_data = sock.recv(2048)
280 | result += recv_data.decode('utf-8')
281 | except socket.error as err_msg:
282 | print('Error receiving data: %s' % err_msg)
283 | if not len(recv_data):
284 | break
285 | sock.close()
286 | return result
287 |
288 | def sendRequestsToApiHost(self, data):
289 | sock = ssl.wrap_socket(socket.socket())
290 | sock.connect((self.apiHost, 443))
291 |
292 | sock.sendall(bytes(data, encoding='utf-8'))
293 | # recv_data = sock.recv(10240)
294 | result = ""
295 | while True:
296 | try:
297 | recv_data = sock.recv(2048)
298 | result += recv_data.decode('utf-8')
299 | except socket.error as err_msg:
300 | print('Error receiving data: %s' % err_msg)
301 | if not len(recv_data):
302 | break
303 | sock.close()
304 | return result
305 |
306 | def launchEntrie(self, paymentToken, priceChecksum):
307 | url = "https://api.nike.com/launch/entries/v2"
308 | headers = {
309 | "Authorization": "Bearer " + self.token,
310 | "Content-Type": "application/json",
311 | "x-nike-caller-id": self.xNikeCallerId,
312 | "User-Agent": self.apiUserAgent,
313 | "X-NewRelic-ID": self.xNewRelicID
314 | }
315 | data = {"deviceId": "", "postpayLink": self.postpayLink, "checkoutId": self.checkoutId, "currency": "CNY",
316 | "paymentToken": paymentToken,
317 | "shipping": {"recipient": self.launchRecipient, "method": "GROUND_SERVICE",
318 | "address": self.launchAddress}, "skuId": self.skuId, "channel": "SNKRS",
319 | "launchId": self.launchId, "locale": "zh_CN", "priceChecksum": priceChecksum}
320 | response = requests.post(url, headers=headers, json=data).json()
321 | return response
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
93 |
94 |
95 |
96 | print
97 | sendall
98 | buy
99 | WebLogin_Chrome
100 | sqlite3
101 | orderStatus
102 | bytes(data
103 | 根据
104 | BuySnkrs
105 | gwtProductFeed
106 | launchEntrie
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | true
131 | DEFINITION_ORDER
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 | 1541600223676
283 |
284 |
285 | 1541600223676
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
--------------------------------------------------------------------------------