返回提交历史
Modified
docs/misc/sign/wbi.md
+193
-163
XFEstudio/bilibili-API-collect
修复Demo访问/x/web-interface/nav被ban的问题 (#991)
尝试向demo代码添加referer头和user-agent来解决被ban
64e1bde
代码差异
1 个文件
+193
-163
@@ -163,7 +163,11 @@ def encWbi(params: dict, img_key: str, sub_key: str):
163
163
164
164
def getWbiKeys() -> tuple[str, str]:
165
165
'获取最新的 img_key 和 sub_key'
166
resp = requests.get('https://api.bilibili.com/x/web-interface/nav')
166
headers = {
167
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
168
'Referer': 'https://www.bilibili.com/'
169
}
170
resp = requests.get('https://api.bilibili.com/x/web-interface/nav', headers=headers)
167
171
resp.raise_for_status()
168
172
json_content = resp.json()
169
173
img_url: str = json_content['data']['wbi_img']['img_url']
@@ -240,7 +244,9 @@ async function getWbiKeys() {
240
244
const res = await fetch('https://api.bilibili.com/x/web-interface/nav', {
241
245
headers: {
242
246
// SESSDATA 字段
243
Cookie: "SESSDATA=xxxxxx"
247
Cookie: "SESSDATA=xxxxxx",
248
User-Agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
249
Referer: 'https://www.bilibili.com/'//对于直接浏览器调用可能不适用
244
250
}
245
251
})
246
252
const { data: { wbi_img: { img_url, sub_url } } } = await res.json()
@@ -283,163 +289,172 @@ bar=514&baz=1919810&foo=114&wts=1684805578&w_rid=bb97e15f28edf445a0e4420d36f0157
283
289
package main
284
290
285
291
import (
286
"crypto/md5"
287
"encoding/hex"
288
"fmt"
289
"io"
290
"net/http"
291
"net/url"
292
"sort"
293
"strconv"
294
"strings"
295
"sync"
296
"time"
297
298
"github.com/tidwall/gjson"
292
"crypto/md5"
293
"encoding/hex"
294
"fmt"
295
"io"
296
"net/http"
297
"net/url"
298
"sort"
299
"strconv"
300
"strings"
301
"sync"
302
"time"
303
304
"github.com/tidwall/gjson"
299
305
)
300
306
301
307
var (
302
mixinKeyEncTab = []int{
303
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
304
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
305
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
306
36, 20, 34, 44, 52,
307
}
308
cache sync.Map
309
lastUpdateTime time.Time
308
mixinKeyEncTab = []int{
309
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
310
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
311
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
312
36, 20, 34, 44, 52,
313
}
314
cache sync.Map
315
lastUpdateTime time.Time
310
316
)
311
317
312
318
func main() {
313
urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091"
314
newUrlStr, err := signAndGenerateURL(urlStr)
315
if err != nil {
316
fmt.Printf("Error: %s", err)
317
return
318
}
319
req, err := http.NewRequest("GET", newUrlStr, nil)
320
if err != nil {
321
fmt.Printf("Error: %s", err)
322
return
323
}
324
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")
325
response, err := http.DefaultClient.Do(req)
326
if err != nil {
327
fmt.Printf("Request failed: %s", err)
328
return
329
}
330
defer response.Body.Close()
331
body, err := io.ReadAll(response.Body)
332
if err != nil {
333
fmt.Printf("Failed to read response: %s", err)
334
return
335
}
336
fmt.Println(string(body))
319
urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091"
320
newUrlStr, err := signAndGenerateURL(urlStr)
321
if err != nil {
322
fmt.Printf("Error: %s", err)
323
return
324
}
325
req, err := http.NewRequest("GET", newUrlStr, nil)
326
if err != nil {
327
fmt.Printf("Error: %s", err)
328
return
329
}
330
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")
331
req.Header.Set("Referer", "https://www.bilibili.com/")
332
response, err := http.DefaultClient.Do(req)
333
if err != nil {
334
fmt.Printf("Request failed: %s", err)
335
return
336
}
337
defer response.Body.Close()
338
body, err := io.ReadAll(response.Body)
339
if err != nil {
340
fmt.Printf("Failed to read response: %s", err)
341
return
342
}
343
fmt.Println(string(body))
337
344
}
338
345
339
346
func signAndGenerateURL(urlStr string) (string, error) {
340
urlObj, err := url.Parse(urlStr)
341
if err != nil {
342
return "", err
343
}
344
imgKey, subKey := getWbiKeysCached()
345
query := urlObj.Query()
346
params := map[string]string{}
347
for k, v := range query {
348
params[k] = v[0]
349
}
350
newParams := encWbi(params, imgKey, subKey)
351
for k, v := range newParams {
352
query.Set(k, v)
353
}
354
urlObj.RawQuery = query.Encode()
355
newUrlStr := urlObj.String()
356
return newUrlStr, nil
347
urlObj, err := url.Parse(urlStr)
348
if err != nil {
349
return "", err
350
}
351
imgKey, subKey := getWbiKeysCached()
352
query := urlObj.Query()
353
params := map[string]string{}
354
for k, v := range query {
355
params[k] = v[0]
356
}
357
newParams := encWbi(params, imgKey, subKey)
358
for k, v := range newParams {
359
query.Set(k, v)
360
}
361
urlObj.RawQuery = query.Encode()
362
newUrlStr := urlObj.String()
363
return newUrlStr, nil
357
364
}
358
365
359
366
func encWbi(params map[string]string, imgKey, subKey string) map[string]string {
360
mixinKey := getMixinKey(imgKey + subKey)
361
currTime := strconv.FormatInt(time.Now().Unix(), 10)
362
params["wts"] = currTime
363
364
// Sort keys
365
keys := make([]string, 0, len(params))
366
for k := range params {
367
keys = append(keys, k)
368
}
369
sort.Strings(keys)
370
371
// Remove unwanted characters
372
for k, v := range params {
373
v = sanitizeString(v)
374
params[k] = v
375
}
376
377
// Build URL parameters
378
query := url.Values{}
379
for _, k := range keys {
380
query.Set(k, params[k])
381
}
382
queryStr := query.Encode()
383
384
// Calculate w_rid
385
hash := md5.Sum([]byte(queryStr + mixinKey))
386
params["w_rid"] = hex.EncodeToString(hash[:])
387
return params
367
mixinKey := getMixinKey(imgKey + subKey)
368
currTime := strconv.FormatInt(time.Now().Unix(), 10)
369
params["wts"] = currTime
370
371
// Sort keys
372
keys := make([]string, 0, len(params))
373
for k := range params {
374
keys = append(keys, k)
375
}
376
sort.Strings(keys)
377
378
// Remove unwanted characters
379
for k, v := range params {
380
v = sanitizeString(v)
381
params[k] = v
382
}
383
384
// Build URL parameters
385
query := url.Values{}
386
for _, k := range keys {
387
query.Set(k, params[k])
388
}
389
queryStr := query.Encode()
390
391
// Calculate w_rid
392
hash := md5.Sum([]byte(queryStr + mixinKey))
393
params["w_rid"] = hex.EncodeToString(hash[:])
394
return params
388
395
}
389
396
390
397
func getMixinKey(orig string) string {
391
var str strings.Builder
392
for _, v := range mixinKeyEncTab {
393
if v < len(orig) {
394
str.WriteByte(orig[v])
395
}
396
}
397
return str.String()[:32]
398
var str strings.Builder
399
for _, v := range mixinKeyEncTab {
400
if v < len(orig) {
401
str.WriteByte(orig[v])
402
}
403
}
404
return str.String()[:32]
398
405
}
399
406
400
407
func sanitizeString(s string) string {
401
unwantedChars := []string{"!", "'", "(", ")", "*"}
402
for _, char := range unwantedChars {
403
s = strings.ReplaceAll(s, char, "")
404
}
405
return s
408
unwantedChars := []string{"!", "'", "(", ")", "*"}
409
for _, char := range unwantedChars {
410
s = strings.ReplaceAll(s, char, "")
411
}
412
return s
406
413
}
407
414
408
415
func updateCache() {
409
if time.Since(lastUpdateTime).Minutes() < 10 {
410
return
411
}
412
imgKey, subKey := getWbiKeys()
413
cache.Store("imgKey", imgKey)
414
cache.Store("subKey", subKey)
415
lastUpdateTime = time.Now()
416
if time.Since(lastUpdateTime).Minutes() < 10 {
417
return
418
}
419
imgKey, subKey := getWbiKeys()
420
cache.Store("imgKey", imgKey)
421
cache.Store("subKey", subKey)
422
lastUpdateTime = time.Now()
416
423
}
417
424
418
425
func getWbiKeysCached() (string, string) {
419
updateCache()
420
imgKeyI, _ := cache.Load("imgKey")
421
subKeyI, _ := cache.Load("subKey")
422
return imgKeyI.(string), subKeyI.(string)
426
updateCache()
427
imgKeyI, _ := cache.Load("imgKey")
428
subKeyI, _ := cache.Load("subKey")
429
return imgKeyI.(string), subKeyI.(string)
423
430
}
424
431
425
432
func getWbiKeys() (string, string) {
426
resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav")
427
if err != nil {
428
fmt.Printf("Error: %s", err)
429
return "", ""
430
}
431
defer resp.Body.Close()
432
body, err := io.ReadAll(resp.Body)
433
if err != nil {
434
fmt.Printf("Error: %s", err)
435
return "", ""
436
}
437
json := string(body)
438
imgURL := gjson.Get(json, "data.wbi_img.img_url").String()
439
subURL := gjson.Get(json, "data.wbi_img.sub_url").String()
440
imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0]
441
subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0]
442
return imgKey, subKey
433
client := &http.Client{}
434
req, err := http.NewRequest("GET", "https://api.bilibili.com/x/web-interface/nav", nil)
435
if err != nil {
436
fmt.Printf("Error creating request: %s", err)
437
return "", ""
438
}
439
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")
440
req.Header.Set("Referer", "https://www.bilibili.com/")
441
resp, err := client.Do(req)
442
if err != nil {
443
fmt.Printf("Error sending request: %s", err)
444
return "", ""
445
}
446
defer resp.Body.Close()
447
body, err := io.ReadAll(resp.Body)
448
if err != nil {
449
fmt.Printf("Error reading response: %s", err)
450
return "", ""
451
}
452
json := string(body)
453
imgURL := gjson.Get(json, "data.wbi_img.img_url").String()
454
subURL := gjson.Get(json, "data.wbi_img.sub_url").String()
455
imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0]
456
subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0]
457
return imgKey, subKey
443
458
}
444
459
```
445
460
@@ -495,23 +510,28 @@ class Program
495
510
}
496
511
497
512
// 获取最新的 img_key 和 sub_key
498
private static async Task<(string, string)> GetWbiKeys()
499
{
500
HttpResponseMessage responseMessage = await _httpClient.SendAsync(new HttpRequestMessage
501
{
502
Method = HttpMethod.Get,
503
RequestUri = new Uri("https://api.bilibili.com/x/web-interface/nav"),
504
});
513
private static async Task<(string, string)> GetWbiKeys()
514
{
515
var httpClient = new HttpClient();
516
httpClient.DefaultRequestHeaders.Add("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");
517
httpClient.DefaultRequestHeaders.Referrer = new Uri("https://www.bilibili.com/");
518
519
HttpResponseMessage responseMessage = await httpClient.SendAsync(new HttpRequestMessage
520
{
521
Method = HttpMethod.Get,
522
RequestUri = new Uri("https://api.bilibili.com/x/web-interface/nav"),
523
});
524
525
JsonNode response = JsonNode.Parse(await responseMessage.Content.ReadAsStringAsync())!;
526
527
string imgUrl = (string)response["data"]!["wbi_img"]!["img_url"]!;
528
imgUrl = imgUrl.Split("/")[^1].Split(".")[0];
529
530
string subUrl = (string)response["data"]!["wbi_img"]!["sub_url"]!;
531
subUrl = subUrl.Split("/")[^1].Split(".")[0];
532
return (imgUrl, subUrl);
533
}
505
534
506
JsonNode response = JsonNode.Parse(await responseMessage.Content.ReadAsStringAsync())!;
507
508
string imgUrl = (string)response["data"]!["wbi_img"]!["img_url"]!;
509
imgUrl = imgUrl.Split("/")[^1].Split(".")[0];
510
511
string subUrl = (string)response["data"]!["wbi_img"]!["sub_url"]!;
512
subUrl = subUrl.Split("/")[^1].Split(".")[0];
513
return (imgUrl, subUrl);
514
}
515
535
516
536
public static async Task Main()
517
537
{
@@ -584,6 +604,8 @@ public class WbiTest {
584
604
map.put("bar", "五一四");
585
605
map.put("baz", 1919810);
586
606
map.put("wts", System.currentTimeMillis() / 1000);
607
map.put("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");
608
map.put("Referer", "https://www.bilibili.com/");
587
609
StringJoiner param = new StringJoiner("&");
588
610
//排序 + 拼接字符串
589
611
map.entrySet().stream()
@@ -679,6 +701,7 @@ class Bilibili {
679
701
$header[] = "Accept: */*";
680
702
$header[] = "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7";
681
703
$header[] = "Connection: close";
704
$header[]="Referer:https://www.bilibili.com/";
682
705
$header[] = "Cache-Control: max-age=0";
683
706
curl_setopt_array($ch, [
684
707
CURLOPT_HTTPGET => 1,
@@ -796,6 +819,7 @@ async fn get_wbi_keys() -> Result<(String, String), reqwest::Error> {
796
819
let ResWbi { data:Data{wbi_img} } = client
797
820
.get("https://api.bilibili.com/x/web-interface/nav")
798
821
.header(USER_AGENT,"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36")
822
.header("Referer","https://www.bilibili.com/")
799
823
// SESSDATA=xxxxx
800
824
.header("Cookie", "SESSDATA=xxxxx")
801
825
.send()
@@ -849,21 +873,27 @@ func biliWbiSign(param: String, completion: @escaping (String?) -> Void) {
849
873
return params
850
874
}
851
875
852
func getWbiKeys(completion: @escaping (Result<(imgKey: String, subKey: String), Error>) -> Void) {
853
AF.request("https://api.bilibili.com/x/web-interface/nav").responseJSON { response in
854
switch response.result {
855
case .success(let value):
856
let json = JSON(value)
857
let imgURL = json["data"]["wbi_img"]["img_url"].string ?? ""
858
let subURL = json["data"]["wbi_img"]["sub_url"].string ?? ""
859
let imgKey = imgURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
860
let subKey = subURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
861
completion(.success((imgKey, subKey)))
862
case .failure(let error):
863
completion(.failure(error))
864
}
865
}
866
}
876
func getWbiKeys(completion: @escaping (Result<(imgKey: String, subKey: String), Error>) -> Void) {
877
let headers: HTTPHeaders = [
878
"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",
879
"Referer": "https://www.bilibili.com/"
880
]
881
882
AF.request("https://api.bilibili.com/x/web-interface/nav", headers: headers).responseJSON { response in
883
switch response.result {
884
case .success(let value):
885
let json = JSON(value)
886
let imgURL = json["data"]["wbi_img"]["img_url"].string ?? ""
887
let subURL = json["data"]["wbi_img"]["sub_url"].string ?? ""
888
let imgKey = imgURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
889
let subKey = subURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
890
completion(.success((imgKey, subKey)))
891
case .failure(let error):
892
completion(.failure(error))
893
}
894
}
895
}
896
867
897
868
898
func calculateMD5(string: String) -> String {
869
899
let data = Data(string.utf8)