返回提交历史
Modified
docs/misc/sign/wbi.md
+143
-127
XFEstudio/bilibili-API-collect
update io and time (#769)
56d0126
代码差异
1 个文件
+143
-127
@@ -279,147 +279,163 @@ bar=514&baz=1919810&foo=114&wts=1684805578&w_rid=bb97e15f28edf445a0e4420d36f0157
279
279
package main
280
280
281
281
import (
282
"crypto/md5"
283
"encoding/hex"
284
"fmt"
285
"io/ioutil"
286
"net/http"
287
"net/url"
288
"sort"
289
"strconv"
290
"strings"
291
"sync"
292
"time"
293
294
"github.com/tidwall/gjson"
282
"crypto/md5"
283
"encoding/hex"
284
"fmt"
285
"io"
286
"net/http"
287
"net/url"
288
"sort"
289
"strconv"
290
"strings"
291
"sync"
292
"time"
293
294
"github.com/tidwall/gjson"
295
295
)
296
296
297
var mixinKeyEncTab = []int{
298
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
299
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
300
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
301
36, 20, 34, 44, 52,
302
}
297
var (
298
mixinKeyEncTab = []int{
299
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
300
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
301
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
302
36, 20, 34, 44, 52,
303
}
304
cache sync.Map
305
lastUpdateTime time.Time
306
)
303
307
304
func getMixinKey(orig string) string {
305
var str strings.Builder
306
for _, v := range mixinKeyEncTab {
307
if v < len(orig) {
308
str.WriteByte(orig[v])
309
}
310
}
311
return str.String()[:32]
308
func main() {
309
urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091"
310
newUrlStr, err := signAndGenerateURL(urlStr)
311
if err != nil {
312
fmt.Printf("Error: %s", err)
313
return
314
}
315
req, err := http.NewRequest("GET", newUrlStr, nil)
316
if err != nil {
317
fmt.Printf("Error: %s", err)
318
return
319
}
320
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
321
response, err := http.DefaultClient.Do(req)
322
if err != nil {
323
fmt.Printf("Request failed: %s", err)
324
return
325
}
326
defer response.Body.Close()
327
body, err := io.ReadAll(response.Body)
328
if err != nil {
329
fmt.Printf("Failed to read response: %s", err)
330
return
331
}
332
fmt.Println(string(body))
312
333
}
313
func EncWbi(params map[string]string, imgKey string, subKey string) map[string]string {
314
mixinKey := getMixinKey(imgKey + subKey)
315
currTime := strconv.FormatInt(time.Now().Unix(), 10)
316
params["wts"] = currTime
317
// Sort keys
318
keys := make([]string, 0, len(params))
319
for k := range params {
320
keys = append(keys, k)
321
}
322
sort.Strings(keys)
323
// Remove unwanted characters
324
for k, v := range params {
325
v = strings.ReplaceAll(v, "!", "")
326
v = strings.ReplaceAll(v, "'", "")
327
v = strings.ReplaceAll(v, "(", "")
328
v = strings.ReplaceAll(v, ")", "")
329
v = strings.ReplaceAll(v, "*", "")
330
params[k] = v
331
}
332
// Build URL parameters
333
var str strings.Builder
334
for _, k := range keys {
335
str.WriteString(fmt.Sprintf("%s=%s&", k, params[k]))
336
}
337
query := strings.TrimSuffix(str.String(), "&")
338
// Calculate w_rid
339
hash := md5.Sum([]byte(query + mixinKey))
340
params["w_rid"] = hex.EncodeToString(hash[:])
341
return params
334
335
func signAndGenerateURL(urlStr string) (string, error) {
336
urlObj, err := url.Parse(urlStr)
337
if err != nil {
338
return "", err
339
}
340
imgKey, subKey := getWbiKeysCached()
341
query := urlObj.Query()
342
params := map[string]string{}
343
for k, v := range query {
344
params[k] = v[0]
345
}
346
newParams := encWbi(params, imgKey, subKey)
347
for k, v := range newParams {
348
query.Set(k, v)
349
}
350
urlObj.RawQuery = query.Encode()
351
newUrlStr := urlObj.String()
352
return newUrlStr, nil
342
353
}
343
354
344
var cache sync.Map
345
var lastUpdateTime time.Time
355
func encWbi(params map[string]string, imgKey, subKey string) map[string]string {
356
mixinKey := getMixinKey(imgKey + subKey)
357
currTime := strconv.FormatInt(time.Now().Unix(), 10)
358
params["wts"] = currTime
346
359
347
func updateCache() {
348
if time.Now().Sub(lastUpdateTime).Minutes() < 10 {
349
return
350
}
351
imgKey, subKey := GetWbiKeys()
352
cache.Store("imgKey", imgKey)
353
cache.Store("subKey", subKey)
354
lastUpdateTime = time.Now()
360
// Sort keys
361
keys := make([]string, 0, len(params))
362
for k := range params {
363
keys = append(keys, k)
364
}
365
sort.Strings(keys)
366
367
// Remove unwanted characters
368
for k, v := range params {
369
v = sanitizeString(v)
370
params[k] = v
371
}
372
373
// Build URL parameters
374
query := url.Values{}
375
for _, k := range keys {
376
query.Set(k, params[k])
377
}
378
queryStr := query.Encode()
379
380
// Calculate w_rid
381
hash := md5.Sum([]byte(queryStr + mixinKey))
382
params["w_rid"] = hex.EncodeToString(hash[:])
383
return params
355
384
}
356
385
357
func GetWbiKeysCached() (string, string) {
358
updateCache()
359
imgKeyI, _ := cache.Load("imgKey")
360
subKeyI, _ := cache.Load("subKey")
361
return imgKeyI.(string), subKeyI.(string)
386
func getMixinKey(orig string) string {
387
var str strings.Builder
388
for _, v := range mixinKeyEncTab {
389
if v < len(orig) {
390
str.WriteByte(orig[v])
391
}
392
}
393
return str.String()[:32]
362
394
}
363
395
364
func GetWbiKeys() (string, string) {
365
resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav")
366
if err != nil {
367
fmt.Println("Error:", err)
368
return "", ""
369
}
370
defer resp.Body.Close()
371
body, err := ioutil.ReadAll(resp.Body)
372
if err != nil {
373
fmt.Println("Error:", err)
374
return "", ""
375
}
376
json := string(body)
377
imgURL := gjson.Get(json, "data.wbi_img.img_url").String()
378
subURL := gjson.Get(json, "data.wbi_img.sub_url").String()
379
imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0]
380
subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0]
381
return imgKey, subKey
396
func sanitizeString(s string) string {
397
unwantedChars := []string{"!", "'", "(", ")", "*"}
398
for _, char := range unwantedChars {
399
s = strings.ReplaceAll(s, char, "")
400
}
401
return s
382
402
}
383
403
384
func SignURL(urlStr string) string {
385
urlObj, _ := url.Parse(urlStr)
386
imgKey, subKey := GetWbiKeysCached()
387
fmt.Println(imgKey, subKey)
388
query := urlObj.Query()
389
params := map[string]string{}
390
for k, v := range query {
391
params[k] = v[0]
392
}
393
newParams := EncWbi(params, imgKey, subKey)
394
for k, v := range newParams {
395
query.Set(k, v)
396
}
397
urlObj.RawQuery = query.Encode()
398
newUrlStr := urlObj.String()
399
return newUrlStr
404
func updateCache() {
405
if time.Since(lastUpdateTime).Minutes() < 10 {
406
return
407
}
408
imgKey, subKey := getWbiKeys()
409
cache.Store("imgKey", imgKey)
410
cache.Store("subKey", subKey)
411
lastUpdateTime = time.Now()
400
412
}
401
func main() {
402
urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091"
403
newUrlStr := utils.SignURL(urlStr) // 签名
404
req, err := http.NewRequest("GET", newUrlStr, nil)
405
if err != nil {
406
return nil, err
407
}
408
// 设置请求头,模拟浏览器
409
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
410
response, err := http.DefaultClient.Do(req)
411
fmt.Println(newUrlStr)
412
if err != nil {
413
fmt.Printf("请求发送失败:%s", err)
414
return nil, err
415
}
416
defer response.Body.Close()
417
body, err := ioutil.ReadAll(response.Body)
418
if err != nil {
419
fmt.Printf("读取响应失败:%s", err)
420
return nil, err
421
}
422
fmt.Println(string(body))
413
414
func getWbiKeysCached() (string, string) {
415
updateCache()
416
imgKeyI, _ := cache.Load("imgKey")
417
subKeyI, _ := cache.Load("subKey")
418
return imgKeyI.(string), subKeyI.(string)
419
}
420
421
func getWbiKeys() (string, string) {
422
resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav")
423
if err != nil {
424
fmt.Printf("Error: %s", err)
425
return "", ""
426
}
427
defer resp.Body.Close()
428
body, err := io.ReadAll(resp.Body)
429
if err != nil {
430
fmt.Printf("Error: %s", err)
431
return "", ""
432
}
433
json := string(body)
434
imgURL := gjson.Get(json, "data.wbi_img.img_url").String()
435
subURL := gjson.Get(json, "data.wbi_img.sub_url").String()
436
imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0]
437
subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0]
438
return imgKey, subKey
423
439
}
424
440
```
425
441