PHP之抖音无水印解析源码

 array('header' => 'User-Agent:' . $UA)));
            $html_text = file_get_contents($link, 0, $context);
            $str = $this->getSubstr($html_text, "itemId: \"", "\",");
            if (!strstr($html_text, "itemId: ")) {
                return false;
            }
            return $str;
        }//短链接支持
        if (strstr($link, "https://www.iesdouyin.com")) {//长链接
            $str = $this->getSubstr($link, "video/", "/?");
            return $str;
        }//长链接支持
        return false;
    }
    private function getOutPutForError($errorMes, $old)
    {
        if ($old) {
            $error = [
                'status' => false,
                'message' => $errorMes
            ];
            return json_encode($error);
        } else {
            $error = [
                'status' => false,
                'errorMes' => $errorMes
            ];
            return json_encode($error);
        }
    }
    private function getFormatVideoData($data)
    {
        $detail = @$data;
        $info = @$detail['share_info'];//视频分享信息
        $aweme_id = @$detail['aweme_id'];
        $user_name = @$detail['author']['nickname'];//作者昵称
        $shortId = @$detail['author']['short_id'];//作者抖音号
        $user_headImg = @$detail['author']['avatar_medium']['url_list'][0];//作者头像
        $image = @$detail['video']['origin_cover']['url_list'][0];//封面图片
        $urls = @$detail['video']['play_addr']['url_list'];//无水印地址
        $music_urls = @$detail['music']['play_url']['url_list'];//音乐地址
        $userId = @$detail['author_user_id'];//用户userId
        $dynamic_cover = @$detail['video']['dynamic_cover']['url_list'][0];//封面动态图地址
        $longVideo = @$detail['long_video'][0]['video']['bit_rate'];//长视频
        if (!$longVideo) {
            $longVideo = [];
        }
        $videoData = [
            'nickname' => $user_name,
            'shortId' => $shortId,
            'userId' => $userId,
            'awemeId' => $aweme_id,
            'headImage' => $user_headImg,
            'image' => $image,
            'dynamic_cover' => $dynamic_cover,
            'urls' => $urls,
            'long_video' => $longVideo,
            'music_urls' => $music_urls,
            'info' => $info,
        ];
        return $videoData;
    }
    private function getDevices()
    {
        return explode("\n", str_replace("\r", "", file_get_contents("./douyinDevice.txt")));//去除回车\r
    }
    private function getVersions()
    {
        return [
            '680' => '6.8.0',
            '251' => '2.5.1',
            '140' => '1.4.0'
        ];
    }
    private function getApis($deviceInfos, $api_n, &$api_positions)
    {
        $versions = $this->getVersions();
        //$base_api="https://aweme.snssdk.com/aweme/v1/aweme/detail/?origin_type=link&retry_type=no_retry&{device_info}&ac=wifi&channel=update&aid=1128&app_name=aweme&version_code={version_code}&version_name={version_name}&device_platform=android&ssmix=a&device_type=MI+8&device_brand=xiaomi&language=zh&os_api=22&os_version=5.1.1&uuid=865166029463703&openudid=ec6d541a2f7350cd&manifest_version_code=251&resolution=1080*1920&dpi=480&update_version_code=2512&ts=1561136204&as=a1e500706c54fd8c8d&cp=004ad55fc8d60ac4e1&aweme_id=";
        $apis = [];
        $rand_devices = [];//随机设备信息
        $devices_size = sizeof($deviceInfos);//实际设备信息条数
        $real_size = $devices_size < $api_n ? $devices_size : $api_n;//最终获取的设备信息数量
        //获取随机设备信息
        for ($i = 0; $i < $real_size;) {
            try {
                $rand = random_int(0, sizeof($deviceInfos) - 1);
                $rand_device = $deviceInfos[$rand];
                if (key_exists($rand_device, $rand_devices)) {
                    continue;
                } else {
                    $rand_devices[] = $rand_device;
                    $i++;
                }
            } catch (Exception $e) {
                exit($this->getOutPutForError("PHP随机数错误"));
            }
            if($rand_device!=""){
                $api_positions[]=$rand;
            }else{
                $api_positions[]=999;
            }
        }
        //生成API
        foreach ($versions as $version_code => $version_name) {
            $version_apis = [];
            foreach ($rand_devices as $device) {
                $version_apis[] = "https://aweme.snssdk.com/aweme/v1/aweme/detail/?origin_type=link&retry_type=no_retry&$device&ac=wifi&channel=update&aid=1128&app_name=aweme&version_code=$version_code&version_name=$version_name&device_platform=android&ssmix=a&device_type=MI+8&device_brand=xiaomi&language=zh&os_api=22&os_version=5.1.1&uuid=865166029463703&openudid=ec6d541a2f7350cd&manifest_version_code=$version_code&resolution=1080*1920&dpi=480&update_version_code=2512&ts=1561136204&as=a1e500706c54fd8c8d&cp=004ad55fc8d60ac4e1&aweme_id=";
            }
            $apis[$version_code] = $version_apis;
        }
        return $apis;
    }
    /**
     * @param $url
     * @param $isFormat
     * @param $old
     * @return false|string
     */
    private function parseVideoByLink($url, $isFormat, $old)
    {
        $awemeId = $this->getAwemeId($url, $this->UA);
        $api_positions = [];//记录device位置
        $api_positions_error = [];//记录哪一个出错
        $api_version = '';//记录使用哪一个版本API
        $api_n = 4;//控制每次取得的设备信息数量
        $deviceInfos = $this->getDevices();
        $versions_apis = $this->getApis($deviceInfos, $api_n, $api_positions);
        if(!$versions_apis) return $this->getOutPutForError("设备信息缺失",$old);
        $header = array("Accept-Encoding: utf-8",
            "User-Agent: okhttp/3.10.0.1"
        );
        $context = stream_context_create(array("http" => array("header" => $header)));
        if ($awemeId) {
            $isSuccess = false;
            foreach ($versions_apis as $version_code => $apis) {
                $count = -1;
                $api_version = $version_code;
                $api_positions_error_version = [];//记录每个版本出错API
                foreach ($apis as $api) {
                    $count++;
                    $api_position = $api_positions[$count];
                    $data = json_decode(file_get_contents($api . $awemeId, 0, $context), true);
                    $detail = @$data['aweme_detail'];
                    $forward_item=@$detail['forward_item'];
                    if($detail&&$forward_item){//用户动态的分享链接
                        $detail=$forward_item;
                    }
                    $short_id=@$detail['author']['short_id'];
                    if ($detail && $short_id) {
                        $isSuccess = true;
                        break;
                    }
                    $api_positions_error_version[] = $api_position;
                }
                $api_positions_error[$version_code] = $api_positions_error_version;
                if ($isSuccess) {
                    break;
                }
            }
            $str_position = null;//储存失败接口位置
            foreach ($api_positions_error as $version_code => $eps) {
                if (!empty($eps))
                    $str_position .= '{' . $version_code . ':';
                foreach ($eps as $ep) {
                    $str_position .= "[$ep]";
                }
                if (!empty($eps))
                    $str_position .= '}';
            }
            if (!$isSuccess) {
                return $this->getOutPutForError("抖音接口调用失败$str_position", $old);
            }
            if($old){
                if($isFormat) {
                    $out = $this->getFormatVideoData($detail);
                }else{
                    $out['data']=$detail;
                }
                $out['status']=true;
                $out['message']=$url;
                $out['api_position']=$api_position;
                $out['error_api']=$str_position;
                $out['api_version']=$api_version;
                $out['dataType_new']=!$old;
                return json_encode($out);
            }else{
                $out=[
                    'status'=>true,
                    'message'=>$url,
                    'data'=>null,
                    'api_position'=>$api_position,
                    'api_version'=>$api_version,
                    'dataType_new'=>!$old,
                    'error_api'=>$str_position
                ];
                if($isFormat) {
                    $out['data'] = $this->getFormatVideoData($detail);
                }else{
                    $out['data']=$detail;
                }
                return json_encode($out);
            }
        }
        return $this->getOutPutForError('链接不正确', $old);
    }
    private function checkParams($url, &$isFormat, &$old)
    {
        if (empty($url)) return false;
        if ($isFormat == null) $isFormat = true;
        if ($old == null) $old = false;
        return true;
    }
    function get($url, $isFormat, $old)
    {
        $pass = $this->checkParams($url, $isFormat, $old);
        if (!$pass)
            return $this->getOutPutForError("地址无效", $old);
        else
            return $this->parseVideoByLink($url, $isFormat, $old);
    }
}
$douyin = new Douyin();
echo $douyin->get($url, $isFormat, $old);

原文地址:
https://github.com/zbfzn/douyin-clear-php/blob/master/parseByLink.php

你可能感兴趣的:(PHP)