发表于 2021-11-13 18:31

申请会员ID:李恒道【申请通过】

1、申 请 I D :李恒道
2、个人邮箱:4548212@qq.com

3、原创技术文章:油猴实战获取快手无水印地址
抓包
地址https://live.kuaishou.com/profile/3x72uw4df7wdq8q?fid=43648984
这里我们抓包
可以发现地址都是https://live.kuaishou.com/live_graphql
通过请求内容的operationName的内容控制获取的数据
根据测试可知,首屏数据的名字为privateFeedsQuery,其他为publicFeedsQuery
返回的数据我大概看了下,只有封面图片,没有视频,点开

发现也是存在id的,所以这里我们应该另想办法
这时候我们发现通过手机分享的单个视频url是无水印的
宝贝 看完了吗~ "夹子音 "高能夹子音 "夹子音变装 https://v.kuaishou.com/dPkfN2 复制此消息,打开【快手】直接观看!

所以抓包开干!
通过抓包分析可知

的返回了无水印视频
为data.visionVideoDetail.photo.photoUrl


提交数据如下
{"operationName":"visionVideoDetail","variables":{"photoId":"3xqmst68mjpue66","page":"detail"},"query":"query visionVideoDetail($photoId: String, $type: String, $page: String, $webPageArea: String) {\nvisionVideoDetail(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"}

这里可以看到photoid是变化的,其他应该没有什么变化,photoid在我们之前的第一个页面可以看到,那我们可以先放下来,构造一个获取无水印的获取函数。
function fuckkuaishouvideo(id,index){
    return new Promise((resolve, reject) => {
      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) {\\nvisionVideoDetail(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){
                let obj=JSON.parse(xhr.responseText)
                let res=obj.data.visionVideoDetail.photo
                if(res===null){
                  console.log('失败的id"',id,index)
                  resolve('success')
                }
                downloadurl.push(res.photoUrl)
                resolve('success')
            }
      });
    })

}
这里需要注意的是如果我们把获取的数据直接放到xhr内\n会出现换行的情况,所以我们需要对这类字符进行转义,在记事本里把\n改成\\n,这样提交的时候会把\\n转义成\n。
                                                    function(data){
                                                      let list=JSON.parse(data)
                                                      console.log('获取了list',list)
                                                      let target=null
                                                      if(list.data.privateFeeds!==undefined){
                                                            target=list.data.privateFeeds
                                                      }
                                                      if(list.data.publicFeeds!==undefined){
                                                            target=list.data.publicFeeds
                                                      }
                                                      if(target!==null){

                                                            for(let index=0;index<target.list.length;index++){
                                                                if(target.list.id===null){
                                                                  savelistid.push('null')
                                                                  zhibo++
                                                                }
                                                                else{
                                                                  if(target.list.imgUrls!==undefined&&target.list.imgUrls.length!==0){
                                                                        for(let imgindex=0;imgindex<target.list.imgUrls.length;imgindex++){
                                                                            imglist.push(target.list.imgUrls)
                                                                        }
                                                                        savelistid.push('null')
                                                                  }else{
                                                                        savelistid.push(target.list.id)
                                                                  }
                                                                }


                                                            }
                                                      }
                                                      let enddownload=document.querySelector('.enddownload')
                                                      console.log('zhibo',zhibo,savelistid.length,savelistid.length-zhibo)
                                                      if(enddownload!==null){
                                                            enddownload.innerHTML=''+(savelistid.length-zhibo)
                                                      }
                                                      resolve(data)
                                                    }
然后继续打一波fetch劫持,这里因为名字不同,但是内容是一致的,所以我先判断前缀部分是什么,然后再进行统一处理。
并将所有的id以及图片地址(获取列表的时候,图片会直接返回给我们)都保存起来。
然后写当我们点击按钮的时候的代码
async function StatToGetVideo(){
    alert('已开始,不要重复点击!')
    let imgnumber=0;
    for(let index=0;index<savelistid.length;index++){
      let id=savelistid
      let result='success'
      if(id!=='null'){
            result= await fuckkuaishouvideo(id,index)
      }else{
            imgnumber++;
      }

      if(result==='success'){
            let startdownload=document.querySelector('.startdownload')
            if(startdownload!==null){
                startdownload.innerHTML=''+(index+1)
            }

      }
    }
    GM_setClipboard([...downloadurl,...imglist].join('\n'))
    alert(savelistid.length+'个共成功'+(downloadurl.length+imgnumber)+'可能存在图片')
    downloadurl=[]

}
代码也是非常简单的,就是通过同步promise,一个一个进行post获取无水印地址,然后存储到数组中,最后通过Gm_setClipboard设置到剪辑板上
...downloadurl是一个解构数组的运算符,join是将数组中每个元素拼接起来。然后清空下载数组。
那么快手批量下载的脚本就做完了

Hmily 发表于 2021-11-15 12:13

I D:李恒道
邮箱:4548212@qq.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。

李恒道 发表于 2021-11-18 02:01

Hmily 发表于 2021-11-15 12:13
I D:李恒道
邮箱:



来报道了,感谢通过
页: [1]
查看完整版本: 申请会员ID:李恒道【申请通过】