上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

快手视频获取求助

[复制链接]
  • TA的每日心情
    无聊
    2023-8-27 10:38
  • 签到天数: 1 天

    [LV.1]初来乍到

    11

    主题

    35

    回帖

    59

    积分

    初级工程师

    积分
    59

    油中2周年喜迎中秋

    发表于 2023-10-11 13:09:01 | 显示全部楼层 | 阅读模式
    悬赏1油猫币已解决

    原教程


    原教程图片:
    image.png
    好像快手更新了页面?这一步获取photoid中我没找到教程中的oparetionName:visionVideoDetail,好像更新为:oparetionName:commentListQuery(含有photoid)
    image.png
    然后个人进行修改原教程中的数据(data):

    function getKusiShowVideo(id) {
      return new Promise((resolve, reject) => {
        //这里需要注意的是如果我们把获取的数据直接放到xhr内\n会出现换行的情况
        //所以我们需要对这类字符进行转义,把\n改成\\n,这样提交的时候会把\\n转义成\n。
        GM_xmlhttpRequest({
          url: "https://www.kuaishou.com/graphql",
          method: "POST",
          data: '{"operationName":"commentListQuery","variables":{"photoId":"'+
          id+
          '","pcursor":""},"query":"query commentListQuery($photoId: String, $pcursor: String) {\\\n  visionCommentList(photoId: $photoId, pcursor: $pcursor) {\\\n    commentCount\\\n    pcursor\\\n    rootComments {\\\n      commentId\\\n      authorId\\\n      authorName\\\n      content\\\n      headurl\\\n      timestamp\\\n      likedCount\\\\n      realLikedCount\\\\n      liked\\\n      status\\\n      authorLiked\\\n      subCommentCount\\\n      subCommentsPcursor\\\n      subComments {\\\n        commentId\\\n        authorId\\\n        authorName\\\n        content\\\n        headurl\\\n        timestamp\\\n        likedCount\\\n        realLikedCount\\\n        liked\\\n        status\\\n        authorLiked\\\n        replyToUserName\\\n        replyTo\\\n        __typename\\\n      }\\\n      __typename\\\n    }\\\n    __typename\\\n  }\\\n}\\\n"}',
            headers: {
            "Content-type": "application/json",
          },
          onload: function (xhr) {
            console.log(xhr.responseText)
            let obj = unsafeWindow.JSON.parse(xhr.responseText);
            let res = obj.data.visionProfilePhotoList.feeds;
            if (res === null) {
              resolve({status:"error"})
            }
            res.forEach((item) =>{
                console.log(item.photo.photoUrl)
                downloadurl.push(item.photo.photoUrl);
            })
            // downloadurl.push(res.photoUrl);
            resolve({
              status:'success',
              // data:res.photoUrl
            });
          },
        });
      });
    }

    但是爆JSON.parse: unexpected character at line 1 column 1 of the JSON data
    image.png


    请问该如何解决?


    本人全部代码:

    // ==UserScript==
    // @name         快手
    // @namespace    http://tampermonkey.net/
    // @version      0.1
    // @description  try to take over the world!
    // @author       You
    // @match        https://www.kuaishou.com/profile/*
    // @icon         https://www.google.com/s2/favicons?sz=64&domain=kuaishou.com
    // @grant        unsafeWindow
    // @run-at       document-start
    // @grant        GM_setClipboard
    // @grant        GM_xmlhttpRequest
    // @connect      *
    // ==/UserScript==
    
    let downloadurl = []
    let idList = []
    function getKusiShowVideo(id) {
      return new Promise((resolve, reject) => {
        //这里需要注意的是如果我们把获取的数据直接放到xhr内\n会出现换行的情况
        //所以我们需要对这类字符进行转义,把\n改成\\n,这样提交的时候会把\\n转义成\n。
        GM_xmlhttpRequest({
          url: "https://www.kuaishou.com/graphql",
          method: "POST",
          data: '{"operationName":"commentListQuery","variables":{"photoId":"'+id+'","pcursor":""},"query":"query commentListQuery($photoId: String, $pcursor: String) {\\\n  visionCommentList(photoId: $photoId, pcursor: $pcursor) {\\\n    commentCount\\\n    pcursor\\\n    rootComments {\\\n      commentId\\\n      authorId\\\n      authorName\\\n      content\\\n      headurl\\\n      timestamp\\\n      likedCount\\\\n      realLikedCount\\\\n      liked\\\n      status\\\n      authorLiked\\\n      subCommentCount\\\n      subCommentsPcursor\\\n      subComments {\\\n        commentId\\\n        authorId\\\n        authorName\\\n        content\\\n        headurl\\\n        timestamp\\\n        likedCount\\\n        realLikedCount\\\n        liked\\\n        status\\\n        authorLiked\\\n        replyToUserName\\\n        replyTo\\\n        __typename\\\n      }\\\n      __typename\\\n    }\\\n    __typename\\\n  }\\\n}\\\n"}',
            headers: {
            "Content-type": "application/json",
          },
          onload: function (xhr) {
            console.log(xhr.responseText)
            let obj = unsafeWindow.JSON.parse(xhr.responseText);
            let res = obj.data.visionProfilePhotoList.feeds;
            if (res === null) {
              resolve({status:"error"})
            }
            res.forEach((item) =>{
                console.log(item.photo.photoUrl)
                downloadurl.push(item.photo.photoUrl);
            })
            // downloadurl.push(res.photoUrl);
            resolve({
              status:'success',
              // data:res.photoUrl
            });
          },
        });
      });
    }
    // function getKusiShowVideo(id) {
    //   return new Promise((resolve, reject) => {
    //     //这里需要注意的是如果我们把获取的数据直接放到xhr内\n会出现换行的情况
    //     //所以我们需要对这类字符进行转义,把\n改成\\n,这样提交的时候会把\\n转义成\n。
    //     GM_xmlhttpRequest({
    //       url: "https://www.kuaishou.com/graphql",
    //       method: "POST",
    //       data:
    //         '{"operationName":"visionVideoDetail","variables":{"photoId":"' +
    //         id +
    //         '","page":"detail"},"query":"query visionVideoDetail($photoId: String, $type: String, $page: String, $webPageArea: String) {\\n  visionVideoDetail(photoId: $photoId, type: $type, page: $page, webPageArea: $webPageArea) {\\n    status\\n    type\\n    author {\\n      id\\n      name\\n      following\\n      headerUrl\\n      __typename\\n    }\\n    photo {\\n      id\\n      duration\\n      caption\\n      likeCount\\n      realLikeCount\\n      coverUrl\\n      photoUrl\\n      liked\\n      timestamp\\n      expTag\\n      llsid\\n      viewCount\\n      videoRatio\\n      stereoType\\n      croppedPhotoUrl\\n      manifest {\\n        mediaType\\n        businessType\\n        version\\n        adaptationSet {\\n          id\\n          duration\\n          representation {\\n            id\\n            defaultSelect\\n            backupUrl\\n            codecs\\n            url\\n            height\\n            width\\n            avgBitrate\\n            maxBitrate\\n            m3u8Slice\\n            qualityType\\n            qualityLabel\\n            frameRate\\n            featureP2sp\\n            hidden\\n            disableAdaptive\\n            __typename\\n          }\\n          __typename\\n        }\\n        __typename\\n      }\\n      __typename\\n    }\\n    tags {\\n      type\\n      name\\n      __typename\\n    }\\n    commentLimit {\\n      canAddComment\\n      __typename\\n    }\\n    llsid\\n    danmakuSwitch\\n    __typename\\n  }\\n}\\n"}',
    //       headers: {
    //         "Content-type": "application/json",
    //       },
    //       onload: function (xhr) {
    //           console.log(xhr.responseText)
    //         let obj = JSON.parse(xhr.responseText);
    //         let res = obj.data.visionVideoDetail.photo;
    //         if (res === null) {
    //           resolve({status:'error'})
    //         }
    //         downloadurl.push(res.photoUrl);
    //         resolve({
    //           status:'success',
    //           data:res.photoUrl
    //         });
    //       },
    //     });
    //   });
    // }
    
    console.log("===========================")
    let oldFetch = unsafeWindow.fetch;
    function hookFetch(...args) {
      return new Promise((resolve, reject) => {
        oldFetch.call(this, ...args).then((response) => {
            // console.log(args)
            // console.log(response)
          if (
            args.length === 2 &&
            args[0].indexOf &&
            args[0].indexOf("/graphql") !== -1 &&
            (args[1].body.indexOf("visionProfilePhotoList") !== -1 )
          ) {
              console.log(args)
              console.log(response)
            console.log("劫持了json函数");
            const oldText = response.text;
            const hookText = function () {
              console.log("text is run");
              return new Promise((resolve, reject) => {
                oldText.apply(this, arguments).then((result) => {
                    console.log("参数:", arguments)
                  console.log("劫持到了文本", result);
                    let resJson = unsafeWindow.JSON.parse(result)
                    resJson.data.visionProfilePhotoList.feeds.forEach((item) => {
                        idList.push(item.photo.id)
                    })
                    // console.log(resJson)
                    // console.log("劫持到了文本", resJson.data.visionProfilePhotoList.feeds[0].photo.photoUrl);
                  resolve(result);
                });
              });
            };
            // response.text = hookText;
            const oldClone = response.clone;
            const hookClone = function () {
              let result = oldClone.apply(this, arguments);
              result.clone = hookClone;
              result.text = hookText;
              return result;
            };
            response.clone = hookClone;
          }
          resolve(response);
        });
      });
    }
    unsafeWindow.fetch = hookFetch;
    
    let getVedioBtn = document.createElement("button")
    getVedioBtn.innerText = "复制视频"
    getVedioBtn.className = "getVedio"
    getVedioBtn.style.background = "#757575";
    getVedioBtn.style.color = "#fff";
    let timer = setInterval(() => {
      if (document.querySelector(".follow-button.user-info-follow") !== null) {
         let target = document.querySelector(".follow-button.user-info-follow");
        //找到了定时器
          target.insertAdjacentElement("afterend", getVedioBtn)
        clearInterval(timer);
      }
    }, 1000);
    
    getVedioBtn.addEventListener("click", StatToGetVideo)
    async function StatToGetVideo() {
      // alert("已开始,不要重复点击!");
      let imgnumber = 0;
      const downloadurl=[]
      console.log(idList)
      for (let index = 0; index < idList.length; index++) {
        let id = idList[index];
        let result = await getKusiShowVideo(id);
        if(result.status==='success'){
          downloadurl.push(result.data)
        }
      }
        console.log(downloadurl)
      GM_setClipboard([...downloadurl].join("\n"));
      alert("共成功:"+downloadurl.length+'个');
    }
    

    最佳答案

    查看完整内容

    现在点击新视频好像没有视频地址的获取的接口了 直接根据列表获取视频地址单独显示
  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    637

    主题

    5206

    回帖

    6085

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6085

    荣誉开发者管理员油中2周年生态建设者喜迎中秋

    发表于 2023-10-11 15:32:26 | 显示全部楼层

    图片.png
    新版本已经不需要发送数据来获取源视频文件地址了

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    637

    主题

    5206

    回帖

    6085

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6085

    荣誉开发者管理员油中2周年生态建设者喜迎中秋

    发表于 2023-10-11 13:09:02 | 显示全部楼层
    梦泽宇 发表于 2023-10-11 16:31
    噢噢,问下道哥,你这个是具体哪个请求,我怎么没找到

    现在点击新视频好像没有视频地址的获取的接口了
    直接根据列表获取视频地址单独显示
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2023-8-27 10:38
  • 签到天数: 1 天

    [LV.1]初来乍到

    11

    主题

    35

    回帖

    59

    积分

    初级工程师

    积分
    59

    油中2周年喜迎中秋

    发表于 2023-10-11 16:31:31 | 显示全部楼层
    李恒道 发表于 2023-10-11 15:32
    [md]![图片.png](data/attachment/forum/202310/11/153210tlopbjrhllcnc3hr.png)
    新版本已经不需要发送数据 ...

    噢噢,问下道哥,你这个是具体哪个请求,我怎么没找到
    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表