因為有時候需要在博客分享一些站外信息,為了讓分享的卡片帶有一些基本信息且可以具有實時性收集了一些 API,寫文章的時候插入 [share url] [/share]
這個短代碼實現自動解析的功能。只需要填入分享的網址不需要其他額外信息,非常方便。
遊戲信息#
Steam 遊戲信息#
對於 Steam 遊戲的分享,最簡單的方式就是用 iframe
標籤調用官方提供的小組件:
但由於 Steam 處於半牆狀態,這東西的加載速度實在是不敢恭維,甚至在某些地方的網絡是直接擺爛加載不出來(例如我家😣),同理 Steam 遊戲信息的 API https://store.steampowered.com/api/appdetails
受制於加載速度也是不太建議使用的。
小黑盒 API#
這裡推薦使用小黑盒的 API https://api.xiaoheihe.cn/game/web/get_game_detail
。
必要的參數是當前的時間戳 _time
以及 Steam 的遊戲 ID appid
。Just like this: https://api.xiaoheihe.cn/game/web/get_game_detail/?_time=1663404056&appid=289070
。
如果請求的時候帶上了 os_type=web&version=999.0.2
這兩個參數的話就必須再帶一個 hkey
參數,否則會提示 hkey 不能为空。網上並沒有最新計算 hkey 的算法,再加上 hkey 的算法變動比較頻繁,所以就不打算花時間去研究這個東西。目前來看小部分遊戲似乎不帶 hkey
參數是無法返回價格信息的,所以如果使用的話需要做好降級處理。
Steam API#
Steam 的 API 必要的參數是遊戲的 ID appids
,推薦帶上查詢遊戲的地區 cc=cn
,這樣返回的價格就是人民幣(CNY);同時帶上 l=schinese
參數,就會將標籤、遊戲簡介之類的文本替換成中文文本(前提是發行商做了遊戲頁面的中文本地化)。
最後由於 Steam API 會返回非常非常非常多的信息,比小黑盒 API 數據量差不多大了一倍,讓本就慢的加載速度雪上加霜。針對這種情況 Steam 提供了一個 filters
參數,允許用戶指定並過濾出所需的信息,不過需要注意的是,這個參數只能過濾出對象集合(即被大括號 {} 或方括號 [] 包圍的數據結構)。這意味著一旦使用 filters 參數進行過濾,所有非對象集合的數據,比如遊戲名稱 name,都將被排除在外。目前尚未發現解決這一限制的方法。用法 Just like this: https://store.steampowered.com/api/appdetails/?appids=814380&cc=cn&l=schinese
。
Note
順帶一提,小黑盒的 API 返回的價格和折扣均是小黑盒的,並非是 Steam 的價格和折扣。
解析效果如下:
遊戲對應平台鏈接#
要想獲取平台遊戲對應的商店頁面鏈接,就需要直接使用平台自帶的 API 了(一般是平台的搜索 API)。
Steam#
對於 Steam 平台,可以通過拼接 steam_appid
到基礎 URL https://store.steampowered.com/app/
來構造遊戲鏈接。
例如,《胡鬧廚房 2》的鏈接是 https://store.steampowered.com/app/728880
。
Switch#
Switch 平台的遊戲搜索可通過 https://search.nintendo.jp/nintendo_soft/search.json
API 實現,其中關鍵參數 q
代表遊戲名稱,支持英文或日文。如果直接使用中文名字,例如 q=集合啦!動物森友會
這樣是獲取不到遊戲信息的。
例如《異度神劍 3》(Xenoblade 3)的 API URL 為: https://search.nintendo.jp/nintendo_soft/search.json?q=Xenoblade3
。通過 API 返回的 id
值,可以構造遊戲在 Switch 商店的鏈接,如:https://store-jp.nintendo.com/list/software/70010000053335.html
。
Ubisoft#
Ubisoft 平台的遊戲搜索 API 為 https://zh-cn.ubisoft.com/news2/search_name
,需要 game_keyword
參數,支持中文遊戲名搜索。
例如,搜索《碧海黑帆》的 API URL 為: https://zh-cn.ubisoft.com/news2/search_name?game_keyword=碧海黑帆
。
將返回的 gameabb
值拼接到 https://zh-cn.ubisoft.com
後,即可得到遊戲鏈接,如:https://zh-cn.ubisoft.com/skull_and_bones
。
Blizzard#
Warning
💩 搜索不準確警告
Blizzard 平台的搜索可能會出現不準確的結果。
Blizzard 平台的遊戲搜索 API 是 https://tw.shop.battle.net/api/search
,需要 q
(遊戲名)和 l
(語言代碼,如 en-us
或 zh-tw
)兩個參數。
例如,搜索《魔獸争霸 3:重制版》的 API URL 為:https://tw.shop.battle.net/api/search?q=Warcraft III: Reforged&l=en-us
。得到返回數據中的 destination
後,拼接到 https://tw.shop.battle.net/zh-tw
基礎 URL,即可構造遊戲鏈接,如:https://tw.shop.battle.net/zh-tw/product/warcraft-iii-reforged
。
其他平台#
對於 Playstation、Xbox、iOS 等平台,目前沒有找到直接的 API,通常採用爬蟲獲取遊戲鏈接。
至於 Epic 因採用加密參數和反爬蟲策略,而 Origin 平台缺少公開 API,因此這些平台會直接使用小黑盒提供的遊戲鏈接。
Bilibili 信息#
視頻#
與 Steam 遊戲卡片分享類似,Bilibili 也可以通過 iframe
標籤分享視頻信息:
Bilibili 視頻信息的 API 調用相對簡單,僅需一個表示視頻的 BV 號或 AV 號的參數 bvid
或 aid
。例如:https://api.bilibili.com/x/web-interface/view?bvid=1NT411u7n9
。
解析效果如下:
動態#
Bilibili 動態信息的 API 同樣簡單,需要一個表示動態的參數 id
,以及一個可選的時區偏移量 timezone_offset
(以分鐘計,默認值為 -480
)。例如:https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?id=706453546894098487
。
Note
動態內容的數組 rich_text_nodes
會以表情包作為數組的分隔符。例如,句子「這是一條文字捏 [給心心] 更多的文字」在數組中將分為三個元素:這是一條文字捏、[給心心]、更多的文字。因此,需要遍歷數組並拼接元素以獲取完整的動態內容。
彈幕#
彈幕信息的 API 需要一個表示視頻的 oid
參數,即視頻的 cid
,可通過視頻信息 API 獲取。例如,獲取 cid
為 834814323 的視頻彈幕:https://api.bilibili.com/x/v1/dm/list.so?oid=834814323
。API 返回的數據格式為 XML。
[!NOTE]
- 視頻的
cid
與視頻的 AV/BV 號不是同一個概念,例如 BV 號為 1NT411u7n9 的視頻,對應的cid
為 834814323。- 返回的數據經過 deflate 壓縮,需要解壓處理。在 PHP 中可以使用
gzinflate()
函數進行解壓。
重點關注以下數據:
-
<maxlimit>
標籤包含視頻最大的彈幕數量。 -
<state>
標籤表示視頻彈幕是否開放,0
表示可以正常發彈幕,1
表示關閉彈幕發送功能。 -
<d p="114.63900,1,25,16777215,1673445087,0,xxxxxxxx,yyyyyyyyyyyyyyyyyyy,10"> 壓力終於給到了二創</d>
標籤包含每一條彈幕的具體信息,詳細信息可參考:bilibili-API-collect 屬性 p 。據此可以得出,內容為壓力終於給到了二創的彈幕在視頻第 114.639 秒出現,是一條普通從右向左滾動的彈幕,字號為標準,字體顏色為白色,在 2023 年 1 月 11 日 21 點 51 分 27 秒發送(時間戳為 1673445087),彈幕池類型為普通彈幕,發送者 mid 的 HASH 為一個 8 位數字字母組合 xxxxxxxx,彈幕 dmid 為一個 19 位純數字 yyyyyyyyyyyyyyyyyyy,當彈幕屏蔽級別大於 10 時可以屏蔽該彈幕。
Github 倉庫信息#
同樣 Github 倉庫信息的 API 也很簡單,只需要 https://api.github.com/repos/
後面接上 {用戶名}/{倉庫名}
即可。Like this: https://api.github.com/repos/SocialSisterYi/bilibili-API-collect
。
解析效果如下:
博客文章 / 頁面信息#
因為 Typecho 升級到了最新的 1.2 版本後原來輸出文章信息的插件用不了,所以只能自己上手加一點功能了。
在 Function.php
中加上:
// 獲取文章信息
public static function getCustom($uid){
$type = is_numeric($uid) ? 'post' : 'page';
$cidType = $type === "post" ? 'cid' : 'slug';
$f = Typecho_Widget::widget('Widget_Archive@'.$uid,'pageSize=1&type='.$type, $cidType.'='.$uid);
$archive_info = ['title'=> $f->title ,'desc' => $f->description ,'category' => $f->category ,'time' => date('Y.m.d', $f->created)];
return $archive_info;
}
然後新建一個獨立頁面模板,通過獲取網址的參數來調用 getCustom()
。
/**
* 文章信息
* @package custom
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
function filter($uid){
preg_match_all("/[a-zA-Z0-9]/",$uid,$a);
return join('',$a[0]);
}
if(!empty(filter($_SERVER["QUERY_STRING"]))){
foreach (explode('&', filter($_SERVER["QUERY_STRING"])) as $value) {
if (strpos($value,'uid')!== false) $uid = explode('=', $value)[1];
}
$returnJson=['state'=>1,'data'=> Func::getCustom($uid)];
echo json_encode($returnJson, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
}else{
$returnJson=['state'=>-2,'message'=>"沒有有效的 UID 輸入"];
echo json_encode($returnJson, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
}
最後後台增加一個獨立頁面,模板選文章信息即可。只有一個對應文章 cid
或者頁面 slug
的參數 uid
,文章調用如下:https://vinking.top/getInfo.html?uid=67
,獨立頁面調用如下:https://vinking.top/getInfo.html?uid=about
。
文章解析效果如下:
目前就使用了這幾個最常用的 API,更多的站外解析就等到有需要的時候再寫吧🙈。
普通網址解析#
最近寫了個 API 可以解析普通頁面,不過有些網址會出現解析不成功的情況,先湊合著用吧...
2022.12.3:經過優化之後已經大幅提高對不同網站的兼容性。
Title 和 Description 都解析成功#
網址 Title 解析失敗#
以《原神》官方網站為例,從下圖中可以觀察到,該頁面的 title
標籤內容是通過名為 config.54af175465c7448a0fa377d065a2d6da.js
的 js 文件動態生成的,這意味著在頁面完全加載完成之前,原始的靜態 HTML 中並不包含 <title>
標籤,因此無法直接獲取到頁面標題。
然而,該頁面定義了 keywords
元數據,所以在無法獲取 <title>
標籤的情況下,我們會選擇 keywords
中的第一個值作為解析後的標題。這樣做的原因是 keywords
中的第一個值通常與頁面標題相符,同時在沒有其他明顯代表網頁標題的信息時,這是一個可行的替代方案。
網址 Description 解析失敗#
網址不存在#
網址境內訪問超時#
網址境內訪問超時的時候自動使用代理再次嘗試,再次訪問超時則降級成『網址不存在』處理
此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://www.vinking.top/posts/codes/game-and-social-media-sharing