Skip to main content

ncm_api_rs/api/
related_playlist.rs

1use crate::error::Result;
2/// 相关歌单
3/// 对应 Node.js module/related_playlist.js
4///
5/// 注意:此接口通过抓取网页 HTML 获取数据,不使用标准 API 请求。
6use crate::request::{ApiClient, ApiResponse};
7use regex_lite::Regex;
8use serde_json::json;
9
10impl ApiClient {
11    /// 相关歌单
12    /// 对应 /related/playlist
13    pub async fn related_playlist(&self, query: &super::Query) -> Result<ApiResponse> {
14        let id = query.get_or("id", "0");
15        let url = format!("https://music.163.com/playlist?id={}", id);
16
17        let resp = self.client.get(&url).send().await?;
18        let status = resp.status().as_u16() as i64;
19        let html = resp.text().await?;
20
21        let pattern = Regex::new(
22            r#"<div class="cver u-cover u-cover-3">[\s\S]*?<img src="([^"]+)">[\s\S]*?<a class="sname f-fs1 s-fc0" href="([^"]+)"[^>]*>([^<]+?)</a>[\s\S]*?<a class="nm nm f-thide s-fc3" href="([^"]+)"[^>]*>([^<]+?)</a>"#,
23        ).map_err(|e| crate::error::NcmError::Unknown(e.to_string()))?;
24
25        let mut playlists = Vec::new();
26        for caps in pattern.captures_iter(&html) {
27            let cover_img_url = caps.get(1).map(|m| m.as_str()).unwrap_or("");
28            let playlist_href = caps.get(2).map(|m| m.as_str()).unwrap_or("");
29            let name = caps.get(3).map(|m| m.as_str()).unwrap_or("");
30            let user_href = caps.get(4).map(|m| m.as_str()).unwrap_or("");
31            let nickname = caps.get(5).map(|m| m.as_str()).unwrap_or("");
32
33            let user_id = user_href
34                .strip_prefix("/user/home?id=")
35                .unwrap_or(user_href);
36            let playlist_id = playlist_href
37                .strip_prefix("/playlist?id=")
38                .unwrap_or(playlist_href);
39            let cover = cover_img_url
40                .strip_suffix("?param=50y50")
41                .unwrap_or(cover_img_url);
42
43            playlists.push(json!({
44                "creator": {
45                    "userId": user_id,
46                    "nickname": nickname
47                },
48                "coverImgUrl": cover,
49                "name": name,
50                "id": playlist_id
51            }));
52        }
53
54        Ok(ApiResponse {
55            status,
56            body: json!({ "code": 200, "playlists": playlists }),
57            cookie: vec![],
58        })
59    }
60}