【Python】自動化搶購茅台,真香。


前言

全民搶購茅台,導致中證白酒指數一路飆升… 跟着大牛喝湯的同時,我也參與了搶購,搶到就是賺到,年關將至,就算自己不喝送禮也是非常 nice 的。

各大平台基本都有搶購茅台的活動,作為互聯網從業人員,大家都知道通過前端手動搶購太慢了,避開前端直接通過接口對服務器發起請求會大大增加搶購的效率。GitHub 上就有大佬開源的搶購項目,本着學習的態度,對代碼仔細閱讀和研究。學習過程中也發現了一些問題,並嘗試進行完善。下文分享學習過程中遇到的問題,以及解決辦法。

原理

首先來看下,實際用戶搶購的步驟(某東為例):

  • 登錄某東商城客戶端

  • 進入商品詳情頁

  • 預約商品

  • 在指定時間進行搶購

程序的實現邏輯也是如此,通過代碼的方式一步一步去實現它。

運行環境 Python 3.7.3

1. 登錄某東商城客戶端

  • 訪問 WEB 登錄頁面,爬取登錄二維碼保存

  • 將圖片彈出,用戶手動掃碼后去循環刷新登錄狀態,獲取用戶身份標識 token/cookies/ticket

2. 進入商品詳情頁

  • 根據商品 ID,獲取商品詳情頁面鏈接,預約鏈接

3. 預約商品

  • 用戶身份標識 + 預約鏈接,完成預約

4. 在指定時間進行搶購

  • 通過電腦時間跟某東服務器時間進行比對,在開放搶購前 500 毫秒發起請求

  • 為快速進行請求,同時開啟 5 個線程去訪問

  • 為保證程序穩定,循環開啟線程時設置時間間隔

准備

1. 程序運行依賴一些第三方庫,需要提前安裝(用的清華源,速度會快一點);

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

2. 獲取用戶標識(必填參數);

  • 進入某東商城 WEB 頁面,選擇一個可下單的商品

  • 進入開發者模式console欄,輸入_JdTdudfp,然后在頁面上點擊下單

  • 將獲取到的eidfp寫入配置文件內

使用

直接運行 main.py,根據提示選擇就行,程序入口代碼如下,非常簡單。

jd_seckill = JdSeckill()
choice_function = input('請選擇:')
if choice_function == '1':   # 預約 
    jd_seckill.reserve()
elif choice_function == '2':  # 搶購
    jd_seckill.seckill_by_proc_pool()  
else:
    print('沒有此功能')
    sys.exit(1)

需要整個項目原代碼后台回復「搶購

改動

我在原項目的基礎上又做了一些改動,其中部分問題已經有人提 issues 了,但是作者還沒來得及改,有些是我根據自己的喜好修改的。

問題 1:

拿到代碼后直接從根目錄執行 main.py 文件時,報異常:FileNotFoundException

原因:讀取配置文件時,沒有使用絕對路徑,使用 abspath 替換並拼接后,解決該問題

問題 2:

預約和搶購需要執行兩次 main.py 文件,分別輸入 1、2 完成對應操作

原因:這個其實作者設計如此,但是我的預期是執行文件后,直接幫我預約,預約完成后進行搶購,所以我把運行入口代碼修改了,執行一次即可

問題 3:

預約邏輯問題,某東預約是每天 10 點 30 分以后即可預約,但是程序設計為必須到達搶購時間才可預約,也就是搶購前 500 毫秒

修改:當前時間大於 10 點 30,即可進行預約

問題 4:

搶購時間需要每次在配置文件內手動修改為當天,如果不修改會判斷當前時間永遠大於搶購時間,出現只要運行程序就發起搶購的問題

修改:增加當天時間自動獲取,如果在 10 點前運行程序,則等待到達搶購時間;如果在 10 點 30 分后手動運行程序,則直接提示搶購時間已過,不再發起請求;針對兩種情況區分了提示信息

問題 5:

原程序是沒有自動終止的,比如搶購 2 分鍾后,結果已經就如此了,往后再搶購意義不大,需要手動去終止程序

解決:增加了一個殺死進程的方法,需要配合定時任務使用

問題 6:

搶購過程中,多進程處理時,都增加了商品名稱和用戶名獲取的邏輯

優化:取消掉該邏輯,因為搶購的商品就一個,所以程序運行前去獲取一次就可以了

問題 7:

搶購過程中出現了一次「當前地區無貨」的情況,無法從日志看出問題

解決:增加了這種情況下的邏輯判斷和日志打印

問題 8:

日志格式過長,打開日志文件,當前屏看到的都是格式,需要左滑才能看到真正的日志

解決:修改日志 formatter 格式,精簡信息

問題 9:

日志文件根據存儲大小來進行判斷是否備份,每天的搶購信息不好區分

優化:根據日期,每天一個日志文件,最多做 5 天備份,超出則刪除最早一天的日志文件

問題 10:

作者使用了 serverChan 進行推送搶購結果到微信,該方法在多線程內,每搶購一次就發送一次消息,調用次數過於頻繁,導致有時被服務拉黑(server醬對發送消息有限制,每人每天上限 500 條,相同內容 5 分鍾內不能重復發送,不同內容 10 分鍾內不能連續發送,每天調用接口超過1000次的用戶將被系統自動拉黑)所以其實發送這么頻繁,真正收不到幾條消息

解決:修改發送消息邏輯,改為定時任務,獲取到最終結果后,再發送消息,預約一條,搶購結果一條。由於微信上推送的內容是僅展示標題,作者是把標題寫死了,所以需要點擊「查看詳情」才能查看結果,為了少點那一下,我就把結果直接改為標題,真的要查看詳細信息了再去點擊。

定時任務

該腳本配合定時任務,不再需要每天掐着點去搶購啦

# [Python] jd seckill maotai
55 09 * * * /usr/bin/python3 workspace/jd_seckill/main.py

# [Python] Stop Python Process
02 10 * * * /usr/bin/python3 workspace/jd_seckill/seckill_stop.py

# [Python] Send wechat message by serverChan
03 10 * * * /usr/bin/python3 workspace/jd_seckill/util.py

如果需要我修改后的代碼,后台回復「加油

其實腳本搶購是次要的,因為在某東各種風控的限制下,搶購速度並不是第一位的,重在參與,結果倒是無所謂了... 如果能從開源腳本中學到一點東西,那么才是真的賺呢。

感謝閱讀。

end



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM