<center><h1>某寶搶購腳本</center></h1>
<center> 簡述</center>
????????最近北京多家冬奧會特許商品零售店外都大排長龍。開幕式過后,多店網紅“冰墩墩”相關毛絨玩具、手辦更是“一墩難求”。某寶冬奧旗艦店搶購搶不到特許零售店更是銷售一空。基于某寶饑餓營銷卻仍然一額難求的情況,戰(zhàn)隊隊長與隊員(某公司python工程師)集合網絡腳本思路,開發(fā)Taobaosnap實現(xiàn)自動搶購。
<center>Taobaosnap</center>
????????Taobaosnap是一個完全開放的工具,用于在淘寶上秒購商品。這是一個用python創(chuàng)建的項目,使用selenium和requests模塊實現(xiàn)登錄和搶購。項目整合網絡腳本思想并進行改進,使用selenium實現(xiàn)遠程登錄和登錄驗證問題。使用無需渲染的捕捉請求,減少訪問和捕捉所需的時間。利用倒計時的思想,實現(xiàn)時間到的自動抓拍。設置使用次數,方便搶購結束后的節(jié)目日志閱讀分析。
????????關于Taobaosnap的介紹描述已經在項目的readme.md寫的非常詳細了,大家可自行訪問開源項目查看。(代碼已于git托管并開源)
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>項目開發(fā)經歷</center>
????????基于筆者對于冰墩墩手動搶購一周仍一墩無購的情況,我們在網絡上找到了兩位開發(fā)者寫的搶購腳本。
<center>requests方案</center>
<b>1.</b>來自’Charles的比卡丘‘的程序使用python開發(fā),使用requests模塊,以requests的方式獲取登錄二維碼進行掃碼登陸后直接進行購物車信息獲取,選擇并搶購。該代碼使用了request請求的方式直接進行搶購.
<b>優(yōu)點:</b>訪問速度快,無需渲染。
<b>缺點:</b>容易觸發(fā)反爬蟲(經大量數據測試,極大多數情況下前四次正常,第五次無法獲取購物車信息),登錄遇到二次校驗或三次校驗(二次校驗概率非常高,三次校驗概率較低。該情況會導致部分賬號無法登錄),搶購第四五次會觸發(fā)校驗。
<center>selenium+webdriver方案</center>
<b>2.</b>來自‘SWHL’師傅的程序同樣使用python開發(fā),使用selenium模塊,以webdriver的形式自動打開瀏覽器,使用瀏覽器自動操做。該項目使用了讀秒的方式計算搶購開始時間,搶購以自動化可視化操做提交訂單。
<b>優(yōu)點:</b>解決了登錄校驗的問題,能夠完成或多次登的錄校驗。讀秒搶購,減少請求次數。
<b>缺點:</b>訪問速度慢,頁面訪問需要渲染,對于網絡速度的要求相對較高。
<center>下面我們來分析一下某寶的反爬蟲策略</center>
selenium抓取一個網站的時候,容易被識別為爬蟲。我們來分析一下識別點:
賬號密碼或手機號登錄容易觸發(fā)反爬蟲機制。
某寶官方提取瀏覽器驅動的指紋特征,比如chromedriver,firefox的webdriver,edge的msedgedriver。
重復提交登錄申請而未完成登錄校驗。
多次提交訂單而未完成校驗。
<center>反爬蟲與應對策略</center>
使用掃碼登錄并完成多次校驗,避免登錄過程被反爬。
經過測試發(fā)現(xiàn),chrome的selenium疑似規(guī)避了反爬蟲策略了。linux系統(tǒng)下使用geckodriver不會觸發(fā)反爬蟲。
由于此處使用webdriver會導致?lián)屬徦俣嚷?,需要等待頁面渲染。requests不便實現(xiàn) 再次使用webdriver彈出校驗。該問題目前暫無良好解決方案。
此處可以參考使用 mitmproxy 蔽掉識別 webdriver 標識符的 js 文件。
- 設置搶購開始時間,讀秒并與系統(tǒng)時間比對。同時設置搶購次數(測試建議五次)。
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>理論與思路</center>
使用selenium模塊與webdriver調用chromedriver完成登錄與登錄校驗。
將selenium登陸完后獲取列表形式的cookie轉換為requests請求字典形式cookie,并使用requests方案獲取購物車信息。
使用讀秒思路比對搶購時間,設置搶購次數限制,減少反爬蟲觸犯幾率。
<b>優(yōu)點:</b>解決登錄校驗的問題,完成或多次登的錄校驗。讀秒搶購,減少請求次數。訪問速度快,無需渲染。不易觸發(fā)反爬蟲機制。
<b>缺點:</b>requests不便實現(xiàn) 再次使用webdriver彈出校驗。
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>項目思路</center>
<center>登錄</center>
使用selenium庫與webdriver實現(xiàn)圖形化登錄,以解決requests登錄方式無法完成登錄驗證的問題。
def cookie_info():
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("start-maximized")
login_url = 'https://login.taobao.com/member/login.jhtml?spm=a21bo.jianhua.201864-2.d1.5af911d9lhGWni&f=top&redirectURL=http%3A%2F%2Fwww.taobao.com%2F'
driver = webdriver.Chrome(options=chrome_options)
print("請盡快掃碼!")
driver.get(login_url)
time.sleep(15) # 預留了安全驗證的時間
driver.refresh() # 刷新頁面
c = driver.get_cookies()
sessions = dict()
for cookie in c:
sessions[cookie['name']] = cookie['value']
#driver.quit()
return sessions
經多次測試,安全驗證時間采用15s停留,以應對二次校驗。
<center>命令參數解析</center>
def parseArgs():
parser = argparse.ArgumentParser(description='淘寶搶購腳本')
parser.add_argument('--time', dest='time', help='秒殺時間', type=str, required=True)
parser.add_argument('--interval', dest='interval', help='搶購商品的時間間隔(單位秒)', type=float, required=True)
parser.add_argument('--l', dest='number', help='搶購商品的次數', type=int, required=True)
args = parser.parse_args()
return args
<center>獲取購物車</center>
def buycartinfo(self):
url = 'https://cart.taobao.com/cart.htm'
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
'sec-fetch-dest': 'document', 'sec-fetch-mode': 'navigate', 'sec-fetch-site': 'none', 'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'cache-control': 'max-age=0'
}
response = self.session.get(url, headers=headers)
# print(response.text)
response_json = re.search('try{var firstData = (.*?);}catch', response.text).group(1)
response_json = json.loads(response_json)
user_id = re.search('\|\^taoMainUser:(.*?):\^', response.headers['s_tag']).group(1)
return response_json, user_id
<center>搶購時間比對與次數限制</center>
時間比對與自動搶購。列出實時時間并比對搶購時間。此處若有因反爬蟲檢測導致提交訂單失敗將給出提示。
print(f'[{time.strftime("%H:%M:%S", time.localtime())} INFO]: 正在嘗試搶購商品***{good_infos[good_id]["title"]}***')
# 對比時間,時間到的話就點擊結算
while True:
now = datetime.datetime.now().strftime('%H:%M:%S.%f')
print(now)
if now > self.Seconds_kill_time:
for i in range(self.number):
try:
is_success = self.buygood(good_infos[good_id], user_id)
except Exception as err:
crawler = re.findall("'NoneType' object has no attribute 'group'",str(err))
if "'NoneType' object has no attribute 'group'" in crawler:
print("已觸發(fā)反爬蟲機制,請稍后嘗試! 錯誤信息如下:\n{0}\n".format(err))
# is_success = False
break
else:
print(f'[{time.strftime("%H:%M:%S", time.localtime())} INFO]: 搶購失敗, 錯誤信息如下: \n{err}\n將在{self.trybuy_interval}秒后重新嘗試.')
is_success = False
if i == self.number-1 and is_success == False:
print("搶購失敗")
break
elif is_success:
print(f'[{time.strftime("%H:%M:%S", time.localtime())} INFO]: 搶購***{good_infos[good_id]["title"]}***成功, 已為您自動提交訂單, 請盡快前往淘寶完成付款.')
# 電腦語音提示
for _ in range(5):
pyttsx3.speak('已經為您搶購到你所需的商品, 請盡快前往淘寶完成付款.')
time.sleep(self.trybuy_interval)
break
break
<center>結算請求</center>
搶購數據使用requests提交,該方案優(yōu)于自動搶購webdriver方案,無需渲染,自動提交搶購請求,提高搶購速度。
url = 'https://buy.taobao.com/auction/order/confirm_order.htm?spm=a1z0d.6639537.0.0.undefined'
headers = {
'cache-control': 'max-age=0', 'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
'origin': 'https://cart.taobao.com', 'content-type': 'application/x-www-form-urlencoded',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'sec-fetch-site': 'same-site', 'sec-fetch-mode': 'navigate', 'sec-fetch-user': '?1',
'sec-fetch-dest': 'document', 'referer': 'https://cart.taobao.com/',
'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8'
}
cart_id, item_id, sku_id, seller_id, cart_params, to_buy_info = info['cart_id'], info['item_id'], info['sku_id'], info['seller_id'], info['cart_params'], info['to_buy_info']
data = {
'item': f'{cart_id}_{item_id}_1_{sku_id}_{seller_id}_0_0_0_{cart_params}_{urllib.parse.quote(str(to_buy_info))}__0',
'buyer_from': 'cart',
'source_time': ''.join(str(int(time.time() * 1000)))
}
disable_warnings()
response = self.session.post(url = url, data = data, headers = headers, verify = False)
order_info = re.search('orderData= (.*?);\n</script>', response.text).group(1)
order_info = json.loads(order_info)
# 發(fā)送提交訂單請求
token = self.session.cookies['_tb_token_']
endpoint = order_info['endpoint']
data = order_info['data']
structure = order_info['hierarchy']['structure']
hierarchy = order_info['hierarchy']
linkage = order_info['linkage']
linkage.pop('url')
submitref = order_info['data']['submitOrderPC_1']['hidden']['extensionMap']['secretValue']
sparam1 = order_info['data']['submitOrderPC_1']['hidden']['extensionMap']['sparam1']
input_charset = order_info['data']['submitOrderPC_1']['hidden']['extensionMap']['input_charset']
event_submit_do_confirm = order_info['data']['submitOrderPC_1']['hidden']['extensionMap']['event_submit_do_confirm']
url = f'https://buy.taobao.com/auction/confirm_order.htm?x-itemid={item_id}&x-uid={user_id}&submitref={submitref}&sparam1={sparam1}'
data_submit = {}
for key, value in data.items():
if value.get('submit') == 'true' or value.get('submit'):
data_submit[key] = value
data = {
'action': '/order/multiTerminalSubmitOrderAction',
'_tb_token_': token,
'event_submit_do_confirm': '1',
'praper_alipay_cashier_domain': 'cashierrz54',
'input_charset': 'utf-8',
'endpoint': urllib.parse.quote(json.dumps(endpoint)),
'data': urllib.parse.quote(json.dumps(data_submit)),
'hierarchy': urllib.parse.quote(json.dumps({"structure": structure})),
'linkage': urllib.parse.quote(json.dumps(linkage))
}
headers = {
'cache-control': 'max-age=0', 'upgrade-insecure-requests': '1', 'origin': 'https://buy.taobao.com',
'content-type': 'application/x-www-form-urlencoded',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'sec-fetch-site': 'same-origin', 'sec-fetch-mode': 'navigate', 'sec-fetch-user': '?1',
'sec-fetch-dest': 'document',
'referer': 'https://buy.taobao.com/auction/order/confirm_order.htm?spm=a1z0d.6639537.0.0.undefined',
'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8'
}
response = self.session.post(url, data=data, headers=headers, verify = False)
if response.status_code == 200: return True
return False
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>使用方式</center>
從https://kaydenlsr.coding.net/public/taobaosnap/taobaosnap/git/files解壓最新版taobaosnap
安裝相關依賴 pip install [modules]
下載chrome瀏覽器和對應的chromedriver,放到python.exe目錄下。項目提供chromedriver version = 99.0.4844.51
運行cmd并運行'python taobaosnap.py --interval [時間間隔] --time [開始時間] --l [頻率]'
<center>例子</center>
$ python taobaosnap.py --interval 0.1 --time 15:59:59:90000000 --l 5
<center>幫助</center>
usage : python taobaosnap.py
--time Buying time and format: 00:00:00:00000000.
--interval Buying time interval.
--l Buying frequency.
<center>測試截圖</center>
(以下非搶購時間測試截圖,已測試其他商品可成功提交訂單)
3.13,筆者使用本程序成功搶購冰墩墩十三個,明天試試搶茅臺吧。
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>如何獲取</center>
Taobaosnap 發(fā)行版可從以下位置獲得
https://kaydenlsr.coding.net/public/taobaosnap/taobaosnap/git/files
Taobaosnap 應該在任何支持python的平臺上運行
Python (http://www.python.org)
注意:有關注意事項,請參閱以下鏈接中的指南
https://kaydenlsr.coding.net/public/taobaosnap/taobaosnap/git/files/master/readme.md
注意:此方案目前不兼容linux系統(tǒng)和mac系統(tǒng)(目前已開發(fā)version=3.2.5支持linux系統(tǒng),大家可自行git上項目查看)
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>依賴</center>
<center>必要的驅動</center>
chromedriver
<center>python依賴庫</center>
-requests
-urllib
-pyttsx3
-prettytable
-argparse
-selenium
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>獲取</center>
<center>github</center>
https://github.com/kaydenlsr/taobaosnap
<center>coding</center>
https://kaydenlsr.coding.net/public/taobaosnap/taobaosnap/git/files
項目各版本使用方法均于readme.md作描述。可以在項目中查看描述文件,或于往期推文閱讀使用方法.
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>其他因素</center>
代碼運行速度
網絡延時
網絡發(fā)包速度
越點路由數量
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>使用建議</center>
將搶購開始時間設置為開始前約0.1秒,搶購時間間隔設置為0.1秒,搶購次數設置為五次。
系統(tǒng)時間與標準網絡時間校對。
使用前約十分鐘登錄賬號,設置好后等待讀秒即可。
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>關于項目</center>
開源項目已發(fā)行五個版本。
version=1.0.5使用requests的方式完成搶購。
version=2.0.3 使用selenium模塊與webdriver調用完成搶購。
version=3.1.5 使用selenium模塊與webdriver調用完成登錄,使用requests的方式完成搶購。
version=3.2.5 簡化了3.1.5版本的的操作。
version=3.3.5 適用于linux的方案。
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>項目作者</center>
<center>spmonkey</center>
<center>K龍</center>
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>特別鳴謝</center>
<center>Charles</center>
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>版本(Version)</center>
<center>Last update 2022.3.12 by K龍 version=3.2.5</center>
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
<center>免責聲明</center>
本項目為開源項目旨在互相學習。禁止違反法律法規(guī)使用本程序。因使用本程序造成的任何后果或相關規(guī)定,作者概不負責。