短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)

序言:
排版可能不是很好看,如有问题请进行在评论区讨论,本系列文章语言采用typescript或Java来进行举例,本系列不止这一篇,这是第一篇。

–写在前面

这是我的写的小程序,有空可以看看,免费,去水印的功能也在上面
短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)_第1张图片

1、分享示例

分享链接采用APP端分享功能,如下:

@神童可心 发了一个快手作品,一起来看!https://v.kuaishou.com/9AYaFk 复制此消息,打开【快手】直接观看!

上面分享的内容有用的是 https://v.kuaishou.com/9AYaFk。
我用的Edge浏览器,打开浏览器,按下F12,转到网络那一栏,勾选保留日志和禁用缓存。
短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)_第2张图片
如果没有网络这一栏,在这里找到点击就可打开
短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)_第3张图片
打开刚刚分享的链接,会发现其中有一个链接返回了视频的数据
短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)_第4张图片

2、接口分析

切换到标头一栏查看请求所需要的参数
短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)_第5张图片

//请求地址
https://video.kuaishou.com/graphql
//请求方式
POST
//请求参数

请求参数 示例
variables {photoId: “3xwgkwpq8hxnvji”, page: “detail”}
operationName visionVideoDetail
query query visionVideoDetail($photoId: String, $type: String, $page: String, $webPageArea: String) {↵ visionVideoDetail(photoId: $photoId, type: $type, page: $page, webPageArea: $webPageArea) {↵ status↵ type↵ author {↵ id↵ name↵ following↵ headerUrl↵ __typename↵ }↵ photo {↵ id↵ duration↵ caption↵ likeCount↵ realLikeCount↵ coverUrl↵ photoUrl↵ liked↵ timestamp↵ expTag↵ llsid↵ viewCount↵ videoRatio↵ stereoType↵ manifest {↵ mediaType↵ businessType↵ version↵ adaptationSet {↵ id↵ duration↵ representation {↵ id↵ defaultSelect↵ backupUrl↵ codecs↵ url↵ height↵ width↵ avgBitrate↵ maxBitrate↵ m3u8Slice↵ qualityType↵ qualityLabel↵ frameRate↵ featureP2sp↵ hidden↵ disableAdaptive↵ __typename↵ }↵ __typename↵ }↵ __typename↵ }↵ __typename↵ }↵ tags {↵ type↵ name↵ __typename↵ }↵ commentLimit {↵ canAddComment↵ __typename↵ }↵ llsid↵ __typename↵ }↵}

以上都是请求参数
发现 在variables这一栏有一个photoId这个参数。
没错,这个参数就是视频的参数。
这个参数怎么获取呢?
很简单就在你访问这个分享链接的时候,返回了一个302跳转地址,在响应头标签Location里
短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)_第6张图片
你会发现这个地址中 photo/ 后面是不是和上面请求的photoId很相似,就是它,拿到它就行了。
在第一步中返回的参数里 data.visionVideoDetail.photo.photoUrl就是我们要拿取的无水印视频,在浏览器打开试试把。
链接:

https://v1.kwaicdn.com/upic/2020/11/15/12/BMjAyMDExMTUxMjU3MTNfMzc2MTcyMDM2XzM5MjY0MTkyNjQ0XzJfMw==_b_Bc75aa7f7089fc157048b515be3d59a6c.mp4?pkey=AAXMLwNBQ2cjoXw0k9Ycji6YwiqCTJrO1jOxKYkj4_mqdmzrx4RjBaDuhDE0e1sE7_DV1HoXa31989DrYVx5Pv0D18HNE6CXuyaElWonPTE0BmGamr_a6VuPvUGydJxw6mM&tag=1-1618053250-xpcwebdetail-0-jncyvtgaz7-7103eae7524e6753&clientCacheKey=3xwgkwpq8hxnvji_b.mp4&tt=b&di=70201f70&bp=10004

到这里 教程就差不多结束了,但是如果你在服务器上进行操作的话,有可能会出现滑块验证,这是快手为了检测是不是机器,这里的话 我们进行一些处理
短视频解析去水印(一):快手去水印(附去滑块验证)2021-05(可用)_第7张图片
如上图,,经过我的测试,Cookie中我们要携带did这个参数过去访问,不然的话会遭遇滑块验证。如果问题重复出现,请把浏览器cookie数据清楚,让其重新生成就可以了。

3、代码示例

好了,到最后环节了,这里我用的是typescript写法,很简单
kuaishou.ts

import {
      result } from "../routers/response";
import {
      formatDate } from "../util/date";
import {
      http } from "../util/http";
import {
      logger } from "../util/log";
import {
      Video } from "./video";

/**
 * 快手
 */
export class KuaiShou extends Video {
     
    async unWaterMarker(url: string): Promise<string> {
     
        try {
     
               let  headers = {
     
                    'Content-Type': 'application/json',
                    "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML,like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 ",
                    "Cookie":'这里填上你的cookie'
                }
                let locatioUrl = await http.location(url, headers, null);
                let photoReg: RegExp = /\/photo\/(\w+)?/
                let photoId = locatioUrl.match(photoReg)![1]
            }

            // let data = { "operationName": "visionVideoDetail", "variables": { "photoId": photoId, "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      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    __typename\n  }\n}\n" }
            let data = {
     
                "operationName": "visionVideoDetail",
                "variables": {
      "photoId": photoId, "page": "selected" },
                "query": "query visionVideoDetail($photoId: String, $type: String, $page: String) {\n  " +
                    "visionVideoDetail(photoId: $photoId, type: $type, page: $page) {\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    " +
                    "  __typename\n    }\n    tags {\n      type\n      name\n      __typename\n    }\n    " +
                    "commentLimit {\n      canAddComment\n      __typename\n    }\n    llsid\n    __typename\n  " +
                    "}\n}\n "
            }
            let base_url = `https://video.kuaishou.com/graphql`
            let res = await http.post(base_url, headers, data, true);

            let body = JSON.parse(JSON.stringify(res))
            logger('kuaishou', `${
       formatDate()}\t${
       JSON.stringify(res)}`)

            let photo = body.data.visionVideoDetail.photo
            let videoUrl = photo.photoUrl
            let videoTitle = photo.caption
            return result(videoUrl, videoTitle)
        } catch (error) {
     
            logger('kuaishou', `${
       formatDate()}\t${
       error}`)

            return ''
        }
    }

}

video.ts

export abstract class Video {
     
    abstract unWaterMarker(url: string): Promise<string>;
}

http.ts

import request from 'request'

export class http {
     

    /**
     * Get请求
     */
    public static get(url: string, headers: any, data: any): Promise<string> {
     
        return new Promise((resolve) => {
     
            request({
     
                url: url,
                method: 'GET',
                qs: data,
                headers: headers
            }, (err, res, body) => {
     
                if (err) {
     
                    resolve('')
                }
                if (res.statusCode = 200) {
     
                    resolve(body)
                } else {
     
                    resolve('')
                }
            });
        });
    }

    public static location(url: string, headers: any, data: any): Promise<string> {
     
        return new Promise((resolve) => {
     
            request({
     
                url: url,
                method: 'GET',
                qs: data,
                headers: headers
            }, (err, res, body) => {
     
                if (err) {
     
                    resolve('')
                }
                if (res.statusCode = 200 || 301 || 302) {
     
                    resolve(res.request.uri.href)
                } else {
     
                    resolve('')
                }
            });
        });
    }

    /**
     * POST 请求
     */
    public static post(url: string, headers: any, data: any, json: boolean): Promise<string> {
     
        return new Promise((resolve) => {
     
            request({
     
                url: url,
                method: 'POST',
                json: json,
                body: data,
                headers: headers
            }, (err, res, body) => {
     
                if (err) {
     
                    resolve('')
                }
                if (res.statusCode = 200) {
     
                    resolve(body)
                }
            });
        });
    }

}

response.ts

export function result(url: string, title: string): any {
     
    return {
     
        "url": url,
        "title": title
    }
}

代码可能写的不怎么样,各位大佬轻喷,也是作为参考用,谢谢大家。

你可能感兴趣的:(去水印,http,node.js,typescript)