
在國外賣到缺貨的RGB口罩,很潮吧。可是又缺貨買不到。所以可以設計一個程式丟到幾器上一旦到了接近開賣時間就開始瘋狂發送請求。其實做搶購程式非常不容易會比爬蟲還要難很多。要解析網頁光這個步驟就很麻煩了。如果要做一個可用性可疊代性高的搶購程式。是非常困難的。會想到的是建立cookie池。半手動化登入更新cookie。還需要代理IP池。如果電商只支持信用卡付款的話。還需要對https 443有一定程度的了解。才可能發送請求。也有可能根本不可能發送。以我的經驗目前能成功的都不是走信用卡付款。而是轉帳先讓server扣庫存。
現在的一些搶購程式我也覺得不可思議。下單不用0.1秒!哪國黑科技?到底是怎麼辦到的。對這方面我很想深入了解。畢竟除了我自己寫過的搶購代碼。我還真的沒看過別的。而且運氣還不錯,成功了!這年頭只要是顯卡或遊戲機都非常難買。以下的代碼就是確認口罩的在庫狀態。一旦回傳True你的程式就可以開始下一步操作。比重新整理網頁還要酷一些。但整體來說用處不大。如果不是秒賣光的產品其實手動重新整理還是搶的到。得到可以購買的消息後馬上進入結帳,也是最難的環節。網站會看cookie, header, session, 一堆有的沒的。光想像就不想再嘗試了。上次代碼能跑是因為剛好都被我找到。但下次呢?其他網站呢?比起一些人的成果我真的太遜了。期待有天我也能有人帶。不然不敢賭頭髮。
#golang 代碼:
package main
import (
"fmt"
"io/ioutil"
"math/rand"
"net/http"
"sync"
"time"
)
// wg建立棧
var wg = sync.WaitGroup{}
//將響應的body以文字形式打印
//也可將響應結果做正則匹配如果偵查到在庫則中斷程序前往結賬步驟
func resp_text(resp *http.Response) []byte {
res, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("%s\n", string(res))
return res
}
//走http協議 像電商api發出請求
func razer(userAgnet string) {
//壓棧當函數執行完畢後會替wg.add 減一
defer wg.Done()
var cli http.Client
//設定請求方式,請求體,請求url
res, _ := http.NewRequest("GET", "https://www2.razer.com/tw-zh/store/dr_json/5576487700", nil)
//設定請求頭的 user agent
res.Header.Set("User-Agent", userAgnet)
//這行是表明你是從哪個網站發起的請求,通常拿來防止跨域請求。所以你沒有設定server就沒有響應
res.Header.Set("Referer", "https://www2.razer.com/tw-zh/store/razer-zephyr-starter-pack")
resp, _ := cli.Do(res)
resp_text(resp)
}
func main() {
startTime := time.Now()
//設置user agent
userAgent := [...]string{
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9",
}
//多併發執行程式 i為發出請求數量
for i := 0; i < 10; i++ {
//將堆棧加一,執行完畢後會由上面的done清除
wg.Add(1)
// go func 可以高併發執行函數
go razer(userAgent[rand.Intn(2)])
}
//在堆棧清空之前不會執行下面的代碼
wg.Wait()
//計時功能
endTime := time.Now()
duration := endTime.Sub(startTime).Seconds()
fmt.Println(duration)
}
所以如果讀者有想法或經驗,或者做過的拜託請跟我交流。