plugin/sousou/json结构分析.md
https://sousou.pro/api.php?action=search&q={关键词}&page={页码}&per_size={每页数量}&type={网盘类型}| 参数名 | 类型 | 必填 | 说明 | 示例值 |
|---|---|---|---|---|
action | string | 是 | 操作类型,固定为 search | search |
q | string | 是 | 搜索关键词 | 遮天 |
page | int | 否 | 页码,从1开始 | 1 |
per_size | int | 否 | 每页返回数量 | 10 |
type | string | 否 | 网盘类型过滤,为空表示全部 | QUARK, BDY, ALY, XUNLEI, UC, 115 |
QUARK - 夸克网盘BDY - 百度网盘ALY - 阿里云盘XUNLEI - 迅雷网盘UC - UC网盘115 - 115网盘{
"code": 200, // 状态码:200表示成功
"msg": "请求成功", // 响应消息
"data": {
"total": 200, // 总记录数
"per_size": 10, // 每页数量
"took": 62, // 搜索耗时(毫秒)
"list": [] // 数据列表数组
}
}
data.list数组中的数据项结构{
"disk_id": "bd8623b72cbb", // 网盘分享ID
"disk_name": "美漫之黑手遮天-西风啸月.txt", // 资源标题/文件名
"disk_pass": "", // 提取码(可能为空)
"disk_type": "QUARK", // 网盘类型标识
"files": "file:美漫之黑手遮天-西风啸月.txt", // 文件列表描述
"doc_id": "cmhfmcz0l2emoae7mf7amvbsi", // 文档ID
"share_user": "安心*海豹", // 分享用户(脱敏)
"share_user_id": "", // 分享用户ID(可能为空)
"shared_time": "2025-10-27 21:38:59", // 分享时间
"rel_movie": "", // 相关电影(可能为空)
"is_mine": true, // 是否我的分享
"tags": null, // 标签数组(可能为null或字符串数组)
"link": "https://pan.quark.cn/s/bd8623b72cbb", // 分享链接
"enabled": true, // 是否启用
"weight": 1, // 权重
"status": 0 // 状态
}
"file:文件名.txt""file:1.mp4\nfile:2.mp4\nfolder:文件夹"null 或字符串数组,如 ["短剧", "电视剧", "国产剧"]YYYY-MM-DD HH:MM:SS| 源字段 | 目标字段 | 说明 |
|---|---|---|
disk_id | UniqueID | 格式: sousou-{disk_id} |
disk_name | Title | 资源标题 |
files | Content | 文件列表描述 |
shared_time | Datetime | 解析为 time.Time 格式 |
tags | Tags | 标签数组(需处理 null 情况) |
link + disk_pass + disk_type | Links | 转换为 Link 数组 |
"" | Channel | 插件搜索结果 Channel 为空字符串 |
API标识 (disk_type) | 系统类型 (Link.Type) | 域名特征 |
|---|---|---|
QUARK | quark | pan.quark.cn |
BDY | baidu | pan.baidu.com |
ALY | aliyun | alipan.com, aliyundrive.com |
XUNLEI | xunlei | pan.xunlei.com |
UC | uc | drive.uc.cn |
115 | 115 | 115.com, 115cdn.com |
TIANYI | tianyi | cloud.189.cn |
CAIYUN | mobile | caiyun.139.com |
123PAN | 123 | 123pan.com, 123912.com |
PIKPAK | pikpak | mypikpak.com |
"2025-10-27 21:38:59""2006-01-02 15:04:05" (Go time.Parse)// 情况1: tags 为 null
"tags": null
// 情况2: tags 为字符串数组
"tags": ["短剧", "电视剧", "国产剧"]
单文件:
"file:美漫之黑手遮天-西风啸月.txt"
多文件:
".mp4
file:29.mp4
file:78.mp4
file:59.mp4
folder:14.弹指遮天"
复杂结构:
"58.mp4
file:90.mp4
file:40.mp4
folder:10.遮天武神"
result := model.SearchResult{
UniqueID: fmt.Sprintf("sousou-%s", item.DiskID),
Title: item.DiskName,
Content: item.Files,
Datetime: parseTime(item.SharedTime),
Tags: processTags(item.Tags),
Links: []model.Link{
{
Type: convertDiskType(item.DiskType),
URL: item.Link,
Password: item.DiskPass,
},
},
Channel: "", // 插件搜索结果Channel为空
}
func convertDiskType(diskType string) string {
switch diskType {
case "BDY":
return "baidu"
case "ALY":
return "aliyun"
case "QUARK":
return "quark"
case "TIANYI":
return "tianyi"
case "UC":
return "uc"
case "CAIYUN":
return "mobile"
case "115":
return "115"
case "XUNLEI":
return "xunlei"
case "123PAN":
return "123"
case "PIKPAK":
return "pikpak"
default:
return "others"
}
}
func parseTime(timeStr string) time.Time {
if timeStr == "" {
return time.Time{} // 零值
}
// 格式:2025-10-27 21:38:59
parsedTime, err := time.Parse("2006-01-02 15:04:05", timeStr)
if err != nil {
return time.Time{} // 解析失败返回零值
}
return parsedTime
}
func processTags(tags interface{}) []string {
if tags == nil {
return nil
}
// 类型断言为字符串数组
if tagArray, ok := tags.([]interface{}); ok {
result := make([]string, 0, len(tagArray))
for _, tag := range tagArray {
if tagStr, ok := tag.(string); ok {
result = append(result, tagStr)
}
}
return result
}
return nil
}
func (p *SousouAsyncPlugin) searchAPI(client *http.Client, keyword string) ([]SousouItem, error) {
maxPages := 3 // 获取前3页
perSize := 30 // 每页30条
// 创建结果通道
resultChan := make(chan []SousouItem, maxPages)
errChan := make(chan error, maxPages)
var wg sync.WaitGroup
// 并发请求每一页
for page := 1; page <= maxPages; page++ {
wg.Add(1)
go func(pageNum int) {
defer wg.Done()
url := fmt.Sprintf("https://sousou.pro/api.php?action=search&q=%s&page=%d&per_size=%d&type=",
url.QueryEscape(keyword), pageNum, perSize)
items, err := p.fetchPage(client, url)
if err != nil {
errChan <- err
return
}
resultChan <- items
}(page)
}
// 等待所有请求完成
go func() {
wg.Wait()
close(resultChan)
close(errChan)
}()
// 收集结果
var allItems []SousouItem
for items := range resultChan {
allItems = append(allItems, items...)
}
return allItems, nil
}
| 特性 | sousou | hunhepan | 说明 |
|---|---|---|---|
| 请求方式 | GET | POST | sousou更简单 |
| API数量 | 1个 | 4个 | sousou单一API |
| 链接格式 | 标准 | 标准 | 都是简单的URL |
| 时间字段 | 有 | 有 | 格式相同 |
| 标签处理 | 可能为null | 可能为null | 需要类型检查 |
| 去重依据 | disk_id | disk_id | 相同逻辑 |
YYYY-MM-DD HH:MM:SS,需要正确的解析格式null,需要进行类型检查和处理{
"code": 200,
"msg": "请求成功",
"data": {
"total": 200,
"per_size": 10,
"took": 62,
"list": [
{
"disk_id": "bd8623b72cbb",
"disk_name": "美漫之黑手遮天-西风啸月.txt",
"disk_pass": "",
"disk_type": "QUARK",
"files": "file:美漫之黑手遮天-西风啸月.txt",
"doc_id": "cmhfmcz0l2emoae7mf7amvbsi",
"share_user": "安心*海豹",
"share_user_id": "",
"shared_time": "2025-10-27 21:38:59",
"rel_movie": "",
"is_mine": true,
"tags": null,
"link": "https://pan.quark.cn/s/bd8623b72cbb",
"enabled": true,
"weight": 1,
"status": 0
}
]
}
}
{
"code": 400,
"msg": "请求失败: 参数错误",
"data": null
}