Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

搜索接口失效问题解决方案 #168

Open
onceisy opened this issue Nov 4, 2022 · 17 comments
Open

搜索接口失效问题解决方案 #168

onceisy opened this issue Nov 4, 2022 · 17 comments

Comments

@onceisy
Copy link

onceisy commented Nov 4, 2022

No description provided.

@onceisy
Copy link
Author

onceisy commented Nov 4, 2022

搜索接口失效问题解决方案

搜索类型:默认为 0 // 0:单曲,1:歌手,2:专辑,3:歌单,7:歌词
代码:直接将以下代码覆盖原来的search.js即可,兼容以前的数据。

module.exports = {
  '/': async ({req, res, request, globalCookie, cache}) => {
    const obj = {...req.query, ...req.body};
    let { uin, qqmusic_key } = globalCookie.userCookie();
    if (Number(obj.ownCookie)) {
      uin = req.cookies.uin || uin;
    }

    const {
      pageNo = 1,
      pageSize = 20,
      key,
      t = 0, // 0:单曲,2:歌单,7:歌词,8:专辑,9:歌手,12:mv
      raw
    } = req.query;
    let total = 0;

    if (!key) {
      return res.send({
        result: 500,
        errMsg: '关键词不能为空',
      });
    }

    // 缓存
    const cacheKey = `search_${key}_${pageNo}_${pageSize}_${t}`;
    const cacheData = cache.get(cacheKey);
    if (cacheData) {
      res && res.send(cacheData);
      return cacheData;
    }

    const url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'

    const typeMap = {
      0: 'song',
      2: 'album',
      1: 'singer',
      3: 'songlist',
      7: 'lyric',
      12: 'mv',
    };
    if (!typeMap[t]) {
      return res.send({
        result: 500,
        errMsg: '搜索类型错误,检查一下参数 t',
      });
    }

    const params = {
      req_1: {
        method: "DoSearchForQQMusicDesktop",
        module: "music.search.SearchCgiService",
        param: {
          num_per_page: Number(pageSize),
          page_num: Number(pageNo),
          query: key,
          search_type: Number(t)
        }
      }
    }
    let result = {}

    try {     
      result = await request({
        url,
        method: 'POST',
        data: params,
        headers: {
          Referer: 'https://y.qq.com'
        },
      });
    } catch (error) {
      return res.send({
        result: 400,
        error
      })
    }

    // 直接返回原生数据
    if (Number(raw)) {
      return res.send(result);
    }
    const response = {
      result: 100,
      data: {
        list: Number(t) === 0 ? formatSongList(result.req_1.data.body[typeMap[t]].list) : result.req_1.data.body[typeMap[t]].list,
        pageNo,
        pageSize,
        total: result.req_1.data.meta.sum,
        key: result.req_1.data.meta.query || key,
        t,
        type: typeMap[t],
      },
    }
    res.send(response);
  },

  // 热搜词
  '/hot': async ({req, res, request}) => {
    const {raw} = req.query;
    const result = await request({
      url: 'https://c.y.qq.com/splcloud/fcgi-bin/gethotkey.fcg',
    });
    if (Number(raw)) {
      return res.send(result);
    }
    res.send({
      result: 100,
      data: result.data.hotkey,
    });
  },

  // 快速搜索
  '/quick': async ({req, res, request}) => {
    const {raw, key} = req.query;
    if (!key) {
      return res.send({
        result: 500,
        errMsg: 'key ?',
      });
    }
    const result = await request(
      `https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?key=${key}&g_tk=5381`,
    );
    if (Number(raw)) {
      return res.send(result);
    }
    return res.send({
      result: 100,
      data: result.data,
    });
  },
}

function formatSongList(list) {
  if (!Array.isArray(list)) {
    return []
  }
  return list.map((item) => {
    // 美化歌曲数据
    return {
      singer: item.singer, // 、
      name: item.title,
      songid: item.id,
      songmid: item.mid,
      songname: item.title,

      albumid: item.album.id,
      albummid: item.album.mid,
      albumname: item.album.name,
      interval: item.interval,

      strMediaMid: item.file.media_mid,
      size128: item.file.size_128mp3,
      size320: item.file.size_320mp3,
      sizeape: item.file.size_ape,
      sizeflac: item.file.size_flac,
      pay: item.pay || {}
    }
  })
}

@643063150
Copy link

报404阿

@onceisy
Copy link
Author

onceisy commented Mar 9, 2023

报404阿

@onceisy onceisy closed this as completed Mar 9, 2023
@onceisy onceisy reopened this Mar 9, 2023
@onceisy
Copy link
Author

onceisy commented Mar 9, 2023

报404阿
检查一下路由写对没

@643063150
Copy link

报404阿
检查一下路由写对没

额 不是覆盖代码就行了吗,不是搞nodejs的不知道咋判断....

@onceisy
Copy link
Author

onceisy commented Mar 10, 2023

报404阿
检查一下路由写对没

额 不是覆盖代码就行了吗,不是搞nodejs的不知道咋判断....

就是直接覆盖就行了啊

@643063150
Copy link

报404阿
检查一下路由写对没

额 不是覆盖代码就行了吗,不是搞nodejs的不知道咋判断....

就是直接覆盖就行了啊

那就奇怪了.我直接把\routes文件夹下的search.js里面的代码直接覆盖成了上面发的,就一直报404错误了

@onceisy
Copy link
Author

onceisy commented Mar 10, 2023

报404阿
检查一下路由写对没

额 不是覆盖代码就行了吗,不是搞nodejs的不知道咋判断....

就是直接覆盖就行了啊

那就奇怪了.我直接把\routes文件夹下的search.js里面的代码直接覆盖成了上面发的,就一直报404错误了

其他的接口能调用?检查一下代码复制完整没有,改完了重启服务。

@643063150
Copy link

其他接口是正常的
TYTU Q 6B{}E6CQ6H$T79MV
这是文件里的代码,我对比了下 应该是一模一样的

module.exports = {
  '/': async ({req, res, request, globalCookie, cache}) => {
    const obj = {...req.query, ...req.body};
    let { uin, qqmusic_key } = globalCookie.userCookie();
    if (Number(obj.ownCookie)) {
      uin = req.cookies.uin || uin;
    }

    const {
      pageNo = 1,
      pageSize = 20,
      key,
      t = 0, // 0:单曲,2:歌单,7:歌词,8:专辑,9:歌手,12:mv
      raw
    } = req.query;
    let total = 0;

    if (!key) {
      return res.send({
        result: 500,
        errMsg: '关键词不能为空',
      });
    }

    // 缓存
    const cacheKey = `search_${key}_${pageNo}_${pageSize}_${t}`;
    const cacheData = cache.get(cacheKey);
    if (cacheData) {
      res && res.send(cacheData);
      return cacheData;
    }

    const url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'

    const typeMap = {
      0: 'song',
      2: 'album',
      1: 'singer',
      3: 'songlist',
      7: 'lyric',
      12: 'mv',
    };
    if (!typeMap[t]) {
      return res.send({
        result: 500,
        errMsg: '搜索类型错误,检查一下参数 t',
      });
    }

    const params = {
      req_1: {
        method: "DoSearchForQQMusicDesktop",
        module: "music.search.SearchCgiService",
        param: {
          num_per_page: Number(pageSize),
          page_num: Number(pageNo),
          query: key,
          search_type: Number(t)
        }
      }
    }
    let result = {}

    try {     
      result = await request({
        url,
        method: 'POST',
        data: params,
        headers: {
          Referer: 'https://y.qq.com'
        },
      });
    } catch (error) {
      return res.send({
        result: 400,
        error
      })
    }

    // 直接返回原生数据
    if (Number(raw)) {
      return res.send(result);
    }
    const response = {
      result: 100,
      data: {
        list: Number(t) === 0 ? formatSongList(result.req_1.data.body[typeMap[t]].list) : result.req_1.data.body[typeMap[t]].list,
        pageNo,
        pageSize,
        total: result.req_1.data.meta.sum,
        key: result.req_1.data.meta.query || key,
        t,
        type: typeMap[t],
      },
    }
    res.send(response);
  },

  // 热搜词
  '/hot': async ({req, res, request}) => {
    const {raw} = req.query;
    const result = await request({
      url: 'https://c.y.qq.com/splcloud/fcgi-bin/gethotkey.fcg',
    });
    if (Number(raw)) {
      return res.send(result);
    }
    res.send({
      result: 100,
      data: result.data.hotkey,
    });
  },

  // 快速搜索
  '/quick': async ({req, res, request}) => {
    const {raw, key} = req.query;
    if (!key) {
      return res.send({
        result: 500,
        errMsg: 'key ?',
      });
    }
    const result = await request(
      `https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?key=${key}&g_tk=5381`,
    );
    if (Number(raw)) {
      return res.send(result);
    }
    return res.send({
      result: 100,
      data: result.data,
    });
  },
}

function formatSongList(list) {
  if (!Array.isArray(list)) {
    return []
  }
  return list.map((item) => {
    // 美化歌曲数据
    return {
      singer: item.singer, // 、
      name: item.title,
      songid: item.id,
      songmid: item.mid,
      songname: item.title,

      albumid: item.album.id,
      albummid: item.album.mid,
      albumname: item.album.name,
      interval: item.interval,

      strMediaMid: item.file.media_mid,
      size128: item.file.size_128mp3,
      size320: item.file.size_320mp3,
      sizeape: item.file.size_ape,
      sizeflac: item.file.size_flac,
      pay: item.pay || {}
    }
  })
}

@643063150
Copy link

报404阿
检查一下路由写对没

额 不是覆盖代码就行了吗,不是搞nodejs的不知道咋判断....

就是直接覆盖就行了啊

那就奇怪了.我直接把\routes文件夹下的search.js里面的代码直接覆盖成了上面发的,就一直报404错误了

其他的接口能调用?检查一下代码复制完整没有,改完了重启服务。

我把服务器重启了下 好了,难道是缓存? 昨天项目重启了好几次都不行 真尴尬

@sSimonz
Copy link

sSimonz commented Oct 26, 2023

你好,替换后,搜索类型为7,对应歌词,会直接崩溃;搜索类型12,对应MV,搜出来的数据为空,应该如何解决呢

@14Kay
Copy link

14Kay commented Nov 10, 2023

有用

@onceisy
Copy link
Author

onceisy commented Nov 13, 2023

你好,替换后,搜索类型为7,对应歌词,会直接崩溃;搜索类型12,对应MV,搜出来的数据为空,应该如何解决呢

没有用过歌词和mv搜索,可以抓包看看对应类型的传参是否有变化

@onceisy
Copy link
Author

onceisy commented Nov 13, 2023

你好,替换后,搜索类型为7,对应歌词,会直接崩溃;搜索类型12,对应MV,搜出来的数据为空,应该如何解决呢

刚刚在其他issue里看到搜索歌词崩溃的原因如下,加上结构检查就行了:

image

@sSimonz
Copy link

sSimonz commented Nov 23, 2023

你好,替换后,搜索类型为7,对应歌词,会直接崩溃;搜索类型12,对应MV,搜出来的数据为空,应该如何解决呢

刚刚在其他issue里看到搜索歌词崩溃的原因如下,加上结构检查就行了:

image

我指的是搜索接口(search.js)对应的搜索类型为歌词(t=7)时会发生崩溃,不是获取歌词的接口(lyric.js)

@sSimonz
Copy link

sSimonz commented Nov 23, 2023

问题已解决,抓包看了下,当搜索类型为歌词时,返回的数据没有lyric字段,实际存放的字段为song;
当搜索类型为mv时,对应的serach_type=4,而不是12。search.js的修改如下:
image
image

@zhemozhiwangddd
Copy link

谢谢你,人间尤物🌹

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants