修复Demo访问/x/web-interface/nav被ban的问题 (#991)

尝试向demo代码添加referer头和user-agent来解决被ban
This commit is contained in:
Ivan Hanloth 2024-04-02 23:21:40 +08:00 committed by GitHub
parent 3802052be8
commit 64e1bde5be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -163,7 +163,11 @@ def encWbi(params: dict, img_key: str, sub_key: str):
def getWbiKeys() -> tuple[str, str]: def getWbiKeys() -> tuple[str, str]:
'获取最新的 img_key 和 sub_key' '获取最新的 img_key 和 sub_key'
resp = requests.get('https://api.bilibili.com/x/web-interface/nav') headers = {
'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',
'Referer': 'https://www.bilibili.com/'
}
resp = requests.get('https://api.bilibili.com/x/web-interface/nav', headers=headers)
resp.raise_for_status() resp.raise_for_status()
json_content = resp.json() json_content = resp.json()
img_url: str = json_content['data']['wbi_img']['img_url'] img_url: str = json_content['data']['wbi_img']['img_url']
@ -240,7 +244,9 @@ async function getWbiKeys() {
const res = await fetch('https://api.bilibili.com/x/web-interface/nav', { const res = await fetch('https://api.bilibili.com/x/web-interface/nav', {
headers: { headers: {
// SESSDATA 字段 // SESSDATA 字段
Cookie: "SESSDATA=xxxxxx" Cookie: "SESSDATA=xxxxxx",
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',
Referer: 'https://www.bilibili.com/'//对于直接浏览器调用可能不适用
} }
}) })
const { data: { wbi_img: { img_url, sub_url } } } = await res.json() 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
package main package main
import ( import (
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
) )
var ( var (
mixinKeyEncTab = []int{ mixinKeyEncTab = []int{
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52, 36, 20, 34, 44, 52,
} }
cache sync.Map cache sync.Map
lastUpdateTime time.Time lastUpdateTime time.Time
) )
func main() { func main() {
urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091" urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091"
newUrlStr, err := signAndGenerateURL(urlStr) newUrlStr, err := signAndGenerateURL(urlStr)
if err != nil { if err != nil {
fmt.Printf("Error: %s", err) fmt.Printf("Error: %s", err)
return return
} }
req, err := http.NewRequest("GET", newUrlStr, nil) req, err := http.NewRequest("GET", newUrlStr, nil)
if err != nil { if err != nil {
fmt.Printf("Error: %s", err) fmt.Printf("Error: %s", err)
return return
} }
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") 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")
response, err := http.DefaultClient.Do(req) req.Header.Set("Referer", "https://www.bilibili.com/")
if err != nil { response, err := http.DefaultClient.Do(req)
fmt.Printf("Request failed: %s", err) if err != nil {
return fmt.Printf("Request failed: %s", err)
} return
defer response.Body.Close() }
body, err := io.ReadAll(response.Body) defer response.Body.Close()
if err != nil { body, err := io.ReadAll(response.Body)
fmt.Printf("Failed to read response: %s", err) if err != nil {
return fmt.Printf("Failed to read response: %s", err)
} return
fmt.Println(string(body)) }
fmt.Println(string(body))
} }
func signAndGenerateURL(urlStr string) (string, error) { func signAndGenerateURL(urlStr string) (string, error) {
urlObj, err := url.Parse(urlStr) urlObj, err := url.Parse(urlStr)
if err != nil { if err != nil {
return "", err return "", err
} }
imgKey, subKey := getWbiKeysCached() imgKey, subKey := getWbiKeysCached()
query := urlObj.Query() query := urlObj.Query()
params := map[string]string{} params := map[string]string{}
for k, v := range query { for k, v := range query {
params[k] = v[0] params[k] = v[0]
} }
newParams := encWbi(params, imgKey, subKey) newParams := encWbi(params, imgKey, subKey)
for k, v := range newParams { for k, v := range newParams {
query.Set(k, v) query.Set(k, v)
} }
urlObj.RawQuery = query.Encode() urlObj.RawQuery = query.Encode()
newUrlStr := urlObj.String() newUrlStr := urlObj.String()
return newUrlStr, nil return newUrlStr, nil
} }
func encWbi(params map[string]string, imgKey, subKey string) map[string]string { func encWbi(params map[string]string, imgKey, subKey string) map[string]string {
mixinKey := getMixinKey(imgKey + subKey) mixinKey := getMixinKey(imgKey + subKey)
currTime := strconv.FormatInt(time.Now().Unix(), 10) currTime := strconv.FormatInt(time.Now().Unix(), 10)
params["wts"] = currTime params["wts"] = currTime
// Sort keys // Sort keys
keys := make([]string, 0, len(params)) keys := make([]string, 0, len(params))
for k := range params { for k := range params {
keys = append(keys, k) keys = append(keys, k)
} }
sort.Strings(keys) sort.Strings(keys)
// Remove unwanted characters // Remove unwanted characters
for k, v := range params { for k, v := range params {
v = sanitizeString(v) v = sanitizeString(v)
params[k] = v params[k] = v
} }
// Build URL parameters // Build URL parameters
query := url.Values{} query := url.Values{}
for _, k := range keys { for _, k := range keys {
query.Set(k, params[k]) query.Set(k, params[k])
} }
queryStr := query.Encode() queryStr := query.Encode()
// Calculate w_rid // Calculate w_rid
hash := md5.Sum([]byte(queryStr + mixinKey)) hash := md5.Sum([]byte(queryStr + mixinKey))
params["w_rid"] = hex.EncodeToString(hash[:]) params["w_rid"] = hex.EncodeToString(hash[:])
return params return params
} }
func getMixinKey(orig string) string { func getMixinKey(orig string) string {
var str strings.Builder var str strings.Builder
for _, v := range mixinKeyEncTab { for _, v := range mixinKeyEncTab {
if v < len(orig) { if v < len(orig) {
str.WriteByte(orig[v]) str.WriteByte(orig[v])
} }
} }
return str.String()[:32] return str.String()[:32]
} }
func sanitizeString(s string) string { func sanitizeString(s string) string {
unwantedChars := []string{"!", "'", "(", ")", "*"} unwantedChars := []string{"!", "'", "(", ")", "*"}
for _, char := range unwantedChars { for _, char := range unwantedChars {
s = strings.ReplaceAll(s, char, "") s = strings.ReplaceAll(s, char, "")
} }
return s return s
} }
func updateCache() { func updateCache() {
if time.Since(lastUpdateTime).Minutes() < 10 { if time.Since(lastUpdateTime).Minutes() < 10 {
return return
} }
imgKey, subKey := getWbiKeys() imgKey, subKey := getWbiKeys()
cache.Store("imgKey", imgKey) cache.Store("imgKey", imgKey)
cache.Store("subKey", subKey) cache.Store("subKey", subKey)
lastUpdateTime = time.Now() lastUpdateTime = time.Now()
} }
func getWbiKeysCached() (string, string) { func getWbiKeysCached() (string, string) {
updateCache() updateCache()
imgKeyI, _ := cache.Load("imgKey") imgKeyI, _ := cache.Load("imgKey")
subKeyI, _ := cache.Load("subKey") subKeyI, _ := cache.Load("subKey")
return imgKeyI.(string), subKeyI.(string) return imgKeyI.(string), subKeyI.(string)
} }
func getWbiKeys() (string, string) { func getWbiKeys() (string, string) {
resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav") client := &http.Client{}
if err != nil { req, err := http.NewRequest("GET", "https://api.bilibili.com/x/web-interface/nav", nil)
fmt.Printf("Error: %s", err) if err != nil {
return "", "" fmt.Printf("Error creating request: %s", err)
} return "", ""
defer resp.Body.Close() }
body, err := io.ReadAll(resp.Body) 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")
if err != nil { req.Header.Set("Referer", "https://www.bilibili.com/")
fmt.Printf("Error: %s", err) resp, err := client.Do(req)
return "", "" if err != nil {
} fmt.Printf("Error sending request: %s", err)
json := string(body) return "", ""
imgURL := gjson.Get(json, "data.wbi_img.img_url").String() }
subURL := gjson.Get(json, "data.wbi_img.sub_url").String() defer resp.Body.Close()
imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0] body, err := io.ReadAll(resp.Body)
subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0] if err != nil {
return imgKey, subKey fmt.Printf("Error reading response: %s", err)
return "", ""
}
json := string(body)
imgURL := gjson.Get(json, "data.wbi_img.img_url").String()
subURL := gjson.Get(json, "data.wbi_img.sub_url").String()
imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0]
subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0]
return imgKey, subKey
} }
``` ```
@ -495,23 +510,28 @@ class Program
} }
// 获取最新的 img_key 和 sub_key // 获取最新的 img_key 和 sub_key
private static async Task<(string, string)> GetWbiKeys() private static async Task<(string, string)> GetWbiKeys()
{ {
HttpResponseMessage responseMessage = await _httpClient.SendAsync(new HttpRequestMessage var httpClient = new HttpClient();
{ 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");
Method = HttpMethod.Get, httpClient.DefaultRequestHeaders.Referrer = new Uri("https://www.bilibili.com/");
RequestUri = new Uri("https://api.bilibili.com/x/web-interface/nav"),
});
JsonNode response = JsonNode.Parse(await responseMessage.Content.ReadAsStringAsync())!; HttpResponseMessage responseMessage = await httpClient.SendAsync(new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://api.bilibili.com/x/web-interface/nav"),
});
string imgUrl = (string)response["data"]!["wbi_img"]!["img_url"]!; JsonNode response = JsonNode.Parse(await responseMessage.Content.ReadAsStringAsync())!;
imgUrl = imgUrl.Split("/")[^1].Split(".")[0];
string imgUrl = (string)response["data"]!["wbi_img"]!["img_url"]!;
imgUrl = imgUrl.Split("/")[^1].Split(".")[0];
string subUrl = (string)response["data"]!["wbi_img"]!["sub_url"]!;
subUrl = subUrl.Split("/")[^1].Split(".")[0];
return (imgUrl, subUrl);
}
string subUrl = (string)response["data"]!["wbi_img"]!["sub_url"]!;
subUrl = subUrl.Split("/")[^1].Split(".")[0];
return (imgUrl, subUrl);
}
public static async Task Main() public static async Task Main()
{ {
@ -584,6 +604,8 @@ public class WbiTest {
map.put("bar", "五一四"); map.put("bar", "五一四");
map.put("baz", 1919810); map.put("baz", 1919810);
map.put("wts", System.currentTimeMillis() / 1000); map.put("wts", System.currentTimeMillis() / 1000);
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");
map.put("Referer", "https://www.bilibili.com/");
StringJoiner param = new StringJoiner("&"); StringJoiner param = new StringJoiner("&");
//排序 + 拼接字符串 //排序 + 拼接字符串
map.entrySet().stream() map.entrySet().stream()
@ -679,6 +701,7 @@ class Bilibili {
$header[] = "Accept: */*"; $header[] = "Accept: */*";
$header[] = "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"; $header[] = "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7";
$header[] = "Connection: close"; $header[] = "Connection: close";
$header[]="Referer:https://www.bilibili.com/";
$header[] = "Cache-Control: max-age=0"; $header[] = "Cache-Control: max-age=0";
curl_setopt_array($ch, [ curl_setopt_array($ch, [
CURLOPT_HTTPGET => 1, CURLOPT_HTTPGET => 1,
@ -796,6 +819,7 @@ async fn get_wbi_keys() -> Result<(String, String), reqwest::Error> {
let ResWbi { data:Data{wbi_img} } = client let ResWbi { data:Data{wbi_img} } = client
.get("https://api.bilibili.com/x/web-interface/nav") .get("https://api.bilibili.com/x/web-interface/nav")
.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") .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")
.header("Referer","https://www.bilibili.com/")
// SESSDATA=xxxxx // SESSDATA=xxxxx
.header("Cookie", "SESSDATA=xxxxx") .header("Cookie", "SESSDATA=xxxxx")
.send() .send()
@ -849,21 +873,27 @@ func biliWbiSign(param: String, completion: @escaping (String?) -> Void) {
return params return params
} }
func getWbiKeys(completion: @escaping (Result<(imgKey: String, subKey: String), Error>) -> Void) { func getWbiKeys(completion: @escaping (Result<(imgKey: String, subKey: String), Error>) -> Void) {
AF.request("https://api.bilibili.com/x/web-interface/nav").responseJSON { response in let headers: HTTPHeaders = [
switch response.result { "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",
case .success(let value): "Referer": "https://www.bilibili.com/"
let json = JSON(value) ]
let imgURL = json["data"]["wbi_img"]["img_url"].string ?? ""
let subURL = json["data"]["wbi_img"]["sub_url"].string ?? "" AF.request("https://api.bilibili.com/x/web-interface/nav", headers: headers).responseJSON { response in
let imgKey = imgURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? "" switch response.result {
let subKey = subURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? "" case .success(let value):
completion(.success((imgKey, subKey))) let json = JSON(value)
case .failure(let error): let imgURL = json["data"]["wbi_img"]["img_url"].string ?? ""
completion(.failure(error)) let subURL = json["data"]["wbi_img"]["sub_url"].string ?? ""
} let imgKey = imgURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
} let subKey = subURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
} completion(.success((imgKey, subKey)))
case .failure(let error):
completion(.failure(error))
}
}
}
func calculateMD5(string: String) -> String { func calculateMD5(string: String) -> String {
let data = Data(string.utf8) let data = Data(string.utf8)