目录
1. 安装 GCC(以 Windows 系统为例,通过 MinGW 安装)
一、引言
在数字化娱乐时代,我们常常希望能够通过简单的命令行操作,快速搜索并播放喜欢的 MV。本文将详细介绍如何使用 C 语言结合libcurl
库实现一个实用的 MV 搜索与播放工具,并且在找到 MV 信息后,联动另一个 API 获取相关内容,实现功能的拓展。通过本文的学习,你将掌握 C 语言中网络请求的基本操作、JSON 数据解析以及命令行程序的开发技巧。
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
// 通用写入回调函数,将数据写入缓冲区
size_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t realsize = size * nmemb;
char* ptr = (char*)userp;
strncat(ptr, (char*)contents, realsize);
return realsize;
}
// 从JSON响应中提取指定字段的值
int extract_json_field(const char* response, const char* prefix, char* value, size_t value_size) {
const char* start = strstr(response, prefix);
if (start == NULL) return 0;
start += strlen(prefix);
const char* end = strchr(start, '"');
if (end == NULL || (size_t)(end - start) >= value_size) return 0;
strncpy(value, start, end - start);
value[end - start] = '\0';
return 1;
}
// 提取MV链接的包装函数
int extract_mv_url(const char* res, char* url, size_t s) {
return extract_json_field(res, "\"url\": \"", url, s);
}
// 提取MV名称的包装函数
int extract_mv_name(const char* res, char* name, size_t s) {
return extract_json_field(res, "\"mv_name\": \"", name, s);
}
// 提取MV歌手的包装函数
int extract_mv_singer(const char* res, char* singer, size_t s) {
return extract_json_field(res, "\"mv_singer\": \"", singer, s);
}
int main(void) {
CURL* curl;
char response[8192] = { 0 };
char mv_url[512] = { 0 }, mv_name[256] = { 0 }, mv_singer[256] = { 0 };
int exit_flag = 0;
curl_global_init(CURL_GLOBAL_DEFAULT);
while (!exit_flag) {
memset(response, 0, sizeof(response));
memset(mv_url, 0, sizeof(mv_url));
memset(mv_name, 0, sizeof(mv_name));
memset(mv_singer, 0, sizeof(mv_singer));
printf("\n请输入歌曲名称(输入exit退出): ");
char search_song[100];
scanf("%99s", search_song);
// 清除输入缓冲区
while (getchar() != '\n');
if (strcmp(search_song, "exit") == 0) break;
curl = curl_easy_init();
if (curl) {
// 构造并发送获取MV信息的请求
char url[512];
snprintf(url, sizeof(url), "https://xiaoapi.cn/API/mv.php?type=kg&msg=%s&n=1", search_song);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
if (curl_easy_perform(curl) == CURLE_OK) {
// 提取MV的各项信息
int valid = extract_mv_url(response, mv_url, sizeof(mv_url))
& extract_mv_name(response, mv_name, sizeof(mv_name))
& extract_mv_singer(response, mv_singer, sizeof(mv_singer));
if (valid && mv_url[0]) {
// 调用新的API获取内容
CURL* new_curl = curl_easy_init();
char new_response[8192] = { 0 };
if (new_curl) {
curl_easy_setopt(new_curl, CURLOPT_URL, "https://api.vvhan.com/api/text/love");
curl_easy_setopt(new_curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(new_curl, CURLOPT_WRITEDATA, new_response);
if (curl_easy_perform(new_curl) == CURLE_OK) {
// 同时输出MV信息和新API的响应内容
printf("\n找到MV:\n 歌曲:%s\n 歌手:%s\n", mv_name, mv_singer);
printf(" 播放链接:%s\n", mv_url);
printf("来自 https://api.vvhan.com/api/text/love 的响应:\n%s\n", new_response);
} else {
fprintf(stderr, "请求 https://api.vvhan.com/api/text/love 失败\n");
}
curl_easy_cleanup(new_curl);
}
char cmd[1024];
snprintf(cmd, sizeof(cmd), "mpv --no-terminal \"%s\"", mv_url);
system(cmd);
} else {
printf("未找到完整MV信息,请尝试其他歌曲\n");
}
}
curl_easy_cleanup(curl);
}
}
curl_global_cleanup();
printf("\n感谢使用,再见!\n");
return 0;
}
编译 -运行
gcc -o music_player music_player.c -lcurl
./music_player
二、用到的工具
1. C 语言编译器
C 语言是一种通用的、高效的编程语言,广泛应用于系统软件、嵌入式开发以及高性能计算等领域。我们将使用 C 语言编写核心代码,常见的 C 语言编译器有GCC
(GNU Compiler Collection)和Clang
。在 Linux 和 macOS 系统上,GCC
通常已经预装;在 Windows 系统上,可以通过安装 MinGW 或 Cygwin 来获取GCC
编译器。
2. libcurl 库
libcurl
是一个功能强大的开源库,用于在程序中进行网络请求操作,支持多种协议(如 HTTP、HTTPS、FTP 等)。它提供了丰富的 API 接口,方便开发者在不同的编程语言中实现网络通信功能。在我们的项目中,将使用libcurl
库发送 HTTP 请求,获取 MV 相关信息以及其他 API 的响应数据。
3. mpv 播放器
mpv
是一款自由、开源的多媒体播放器,支持多种音频和视频格式,具有强大的功能和高度的可定制性。我们将使用mpv
播放器来播放搜索到的 MV,通过在命令行中调用mpv
命令实现自动播放。
三、安装教程
1. 安装 GCC(以 Windows 系统为例,通过 MinGW 安装)
2. 安装 libcurl 库
Linux 系统(以 Ubuntu 为例)
- 打开终端,输入以下命令安装
libcurl
库及其开发包:
sudo apt-get update
sudo apt-get install libcurl4-openssl-dev
- 安装完成后,系统会自动将
libcurl
库的头文件和链接库文件安装到相应的目录(通常是/usr/include
和/usr/lib
)。
3. 安装 mpv 播放器
Linux 系统(以 Ubuntu 为例)
打开终端,输入以下命令安装mpv
播放器:
sudo apt-get install mpv
四、代码详解
1. 引入头文件
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
stdio.h
:提供标准输入输出函数,如printf
、scanf
等。curl/curl.h
:引入libcurl
库的头文件,用于网络请求操作。stdlib.h
:包含一些通用的函数,如内存分配函数malloc
、free
,以及进程终止函数exit
等。string.h
:提供字符串处理函数,如strcpy
、strcat
、strcmp
等。
2. 写入回调函数
size_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t realsize = size * nmemb;
char* ptr = (char*)userp;
strncat(ptr, (char*)contents, realsize);
return realsize;
}
该函数是libcurl
库的写入回调函数,用于将从网络请求中接收到的数据写入指定的缓冲区。contents
指向接收到的数据,size
表示每个数据块的大小,nmemb
表示数据块的数量,userp
是用户自定义的指针,指向用于存储数据的缓冲区。函数将接收到的数据追加到缓冲区中,并返回实际写入的数据大小。
3. JSON 字段提取函数
int extract_json_field(const char* response, const char* prefix, char* value, size_t value_size) {
const char* start = strstr(response, prefix);
if (start == NULL) return 0;
start += strlen(prefix);
const char* end = strchr(start, '"');
if (end == NULL || (size_t)(end - start) >= value_size) return 0;
strncpy(value, start, end - start);
value[end - start] = '\0';
return 1;
}
此函数用于从 JSON 格式的响应数据中提取指定字段的值。它首先在响应字符串response
中查找指定的前缀prefix
,找到后计算字段值的起始和结束位置,然后将字段值复制到value
缓冲区中,并确保不会超出缓冲区的大小。如果成功提取到字段值,则返回 1;否则返回 0。
4. 提取 MV 信息的包装函数
int extract_mv_url(const char* res, char* url, size_t s) {
return extract_json_field(res, "\"url\": \"", url, s);
}
int extract_mv_name(const char* res, char* name, size_t s) {
return extract_json_field(res, "\"mv_name\": \"", name, s);
}
int extract_mv_singer(const char* res, char* singer, size_t s) {
return extract_json_field(res, "\"mv_singer\": \"", singer, s);
}
这些函数是对extract_json_field
函数的封装,分别用于提取 MV 的链接、名称和歌手信息。通过指定不同的前缀,调用extract_json_field
函数实现具体字段的提取。
5. 主函数
int main(void) {
CURL* curl;
char response[8192] = { 0 };
char mv_url[512] = { 0 }, mv_name[256] = { 0 }, mv_singer[256] = { 0 };
int exit_flag = 0;
curl_global_init(CURL_GLOBAL_DEFAULT);
while (!exit_flag) {
memset(response, 0, sizeof(response));
memset(mv_url, 0, sizeof(mv_url));
memset(mv_name, 0, sizeof(mv_name));
memset(mv_singer, 0, sizeof(mv_singer));
printf("\n请输入歌曲名称(输入exit退出): ");
char search_song[100];
scanf("%99s", search_song);
// 清除输入缓冲区
while (getchar() != '\n');
if (strcmp(search_song, "exit") == 0) break;
curl = curl_easy_init();
if (curl) {
// 构造并发送获取MV信息的请求
char url[512];
snprintf(url, sizeof(url), "https://xiaoapi.cn/API/mv.php?type=kg&msg=%s&n=1", search_song);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
if (curl_easy_perform(curl) == CURLE_OK) {
// 提取MV的各项信息
int valid = extract_mv_url(response, mv_url, sizeof(mv_url))
& extract_mv_name(response, mv_name, sizeof(mv_name))
& extract_mv_singer(response, mv_singer, sizeof(mv_singer));
if (valid && mv_url[0]) {
// 调用新的API获取内容
CURL* new_curl = curl_easy_init();
char new_response[8192] = { 0 };
if (new_curl) {
curl_easy_setopt(new_curl, CURLOPT_URL, "https://api.vvhan.com/api/text/love");
curl_easy_setopt(new_curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(new_curl, CURLOPT_WRITEDATA, new_response);
if (curl_easy_perform(new_curl) == CURLE_OK) {
// 同时输出MV信息和新API的响应内容
printf("\n找到MV:\n 歌曲:%s\n 歌手:%s\n", mv_name, mv_singer);
printf(" 播放链接:%s\n", mv_url);
printf("来自 https://api.vvhan.com/api/text/love 的响应:\n%s\n", new_response);
} else {
fprintf(stderr, "请求 https://api.vvhan.com/api/text/love 失败\n");
}
curl_easy_cleanup(new_curl);
}
char cmd[1024];
snprintf(cmd, sizeof(cmd), "mpv --no-terminal \"%s\"", mv_url);
system(cmd);
} else {
printf("未找到完整MV信息,请尝试其他歌曲\n");
}
}
curl_easy_cleanup(curl);
}
}
curl_global_cleanup();
printf("\n感谢使用,再见!\n");
return 0;
}
- 初始化和变量定义:定义了
CURL
指针、响应缓冲区、MV 信息缓冲区以及退出标志等变量,并初始化libcurl
库。 - 循环输入:通过一个
while
循环,持续提示用户输入歌曲名称。如果用户输入exit
,则设置退出标志,结束循环。 - 发送 MV 信息请求:在每次循环中,构造获取 MV 信息的 API 请求 URL,使用
libcurl
库发送请求,并将响应数据存储在response
缓冲区中。 - 提取 MV 信息:调用
extract_mv_url
、extract_mv_name
和extract_mv_singer
函数,从响应数据中提取 MV 的链接、名称和歌手信息。 - 调用新 API 并输出结果:如果成功提取到完整的 MV 信息,再次使用
libcurl
库发送请求到https://api.vvhan.com/api/text/love
,获取额外的内容。将 MV 信息和新 API 的响应内容同时输出到控制台。 - 播放 MV:构造
mpv
播放器的命令,通过system
函数调用mpv
命令,播放搜索到的 MV。 - 清理资源:在程序结束前,清理
libcurl
库的资源,释放相关内存。
五、总结
通过本文的介绍,我们成功使用 C 语言结合libcurl
库实现了一个功能丰富的 MV 搜索与播放工具,并联动了另一个 API 获取额外内容。在这个过程中,我们学习了libcurl
库的基本使用方法、JSON 数据解析技巧以及如何在 C 语言中调用外部程序。希望本文对你在 C 语言网络编程和实际项目开发中有所帮助。你可以根据自己的需求,进一步拓展和优化这个程序,例如添加错误处理机制、优化代码结构等。