setName('zm') ->setDescription('zm command'); } protected function execute(Input $input, Output $output) { // 输出结果 // $output->writeln("Hello, {$name}!"); // $output->writeln("Option: {$option}"); $this->aria2 = new Aria2('http://127.0.0.1:16800/jsonrpc','11223344'); //实例化aria2对象 $this->aria2->setOption('enable-async-dns', true); //设置异步dns解析 $this->aria2->setOption('enable-http-pipelining', true); //设置http管道化 $this->aria2->setOption('enable-http-keep-alive', true); //设置http保持连接 $this->completed = false; while($this->completed === false){ try { $this->start(); } catch (\Exception $e) { halt($e); sleep(3); } } dump('下载完成!'); } protected function start() { $savepath = 'E:/zm'; $lable = $this->getLable(); if($lable['code'] == 0){ $leftLabel = $lable['data']['leftLabel']; foreach ($leftLabel[0]['children'] as $key => $course) { $lable_title = $course['title']; $lable_id = $course['id']; $next = true; $curr_page = 1; $curr_total = 0; while($next){ $curr = $this->getCurr($lable_id,$curr_page); $currs = $curr['data']['curriculum']; foreach ($currs as $key => $value) { $curr_total++; $curr_item = $value; $curr_item_title = $curr_item['title']; $c = $savepath . '/' . $lable_title . '/' . $curr_item_title; // dump('存储路径',$c); is_dir($c) || mkdir($c,0755,true); $author = $savepath . '/' . $lable_title . '/' . $curr_item_title . '/' . '作者.txt'; $this->savetxt($author,$curr_item['author']); $introduce = $savepath . '/' . $lable_title . '/' . $curr_item_title . '/' . '介绍.txt'; $this->savetxt($introduce,$curr_item['introduce']); $cover = $curr_item['cover']; $this->download($cover,$c); $cover_name = basename($cover); $cover_path = "{$c}/{$cover_name}-下载地址.txt"; $this->savetxt($cover_path,$cover); $curr_details = $this->getCurrDetails($curr_item['id']); foreach($curr_details['data']['curriculum']['allClassSectionTrue'] as $class){ $class_path = $c . '/' . $class['title']; is_dir($class_path) || mkdir($class_path,0755,true); $class_details = $this->getClassDetails($class['id']); dump($class_path,$class_details); $class_id = $class_details['data']['classSection']['id']; if(!empty($class_details['data']['classSection']['video'])){ $this->download($class_details['data']['classSection']['video'],$class_path); } if(!empty($class_details['data']['classSection']['courseware'])){ $this->download($class_details['data']['classSection']['courseware'],$class_path); } if(!empty($class_details['data']['classSection']['construction_draw'])){ $this->download($class_details['data']['classSection']['construction_draw'],$class_path); } if(!empty($class_details['data']['classSection']['construction_draw_3d'])){ $this->download($class_details['data']['classSection']['construction_draw_3d'],$class_path); } foreach($class_details['data']['classSection']['allEnclosure'] as $enclosure){ $parts = explode("{$class_id}/", $enclosure['url']); $path = parse_url($enclosure['url'], PHP_URL_PATH); $parts = explode('/', $path); $storage = $class_path . '/' . urldecode($parts[count($parts)-2]); is_dir($storage) || mkdir($storage,0755,true); $downloadurl = $storage . '/' . urldecode(end($parts)) . '-下载地址.txt'; $this->savetxt($downloadurl,urldecode($enclosure['url'])); // $this->download($enclosure['url'],$storage); } } } $curr_page++; if($curr_total >= $curr['data']['total']){ $next = false; break; } } // exit(); } dump($leftLabel); }else{ dump($lable['msg']); exit(); } exit(); } private function checkfile($url,$file) { dump($url,$file); $key = 'zm_check_header_' . md5($url); try { if(($head = Cache::get($key,null)) === NULL ){ $head = []; $client = new Client(['timeout' => 5.0,]); try { // 发送 HEAD 请求,并添加自定义请求头 $response = $client->head($url, [ 'headers' => [ 'User-Agent'=>'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.489.400 QQBrowser/13.7.6351.400', 'referer'=>'https://edu.zmrobo.com/courses', ], ]); // 读取响应状态码 $statusCode = $response->getStatusCode(); if($statusCode != 200){ dump('文件head请求失败,状态码:'.$statusCode); return 0; } // 获取全部响应头(返回关联数组) $headers = $response->getHeaders(); foreach ($headers as $name => $values) { $head[$name] = implode(', ', $values); } dump($head); } catch (\GuzzleHttp\Exception\RequestException $e) { dump("文件head请求失败: " . $e->getMessage()); return 0; } Cache::set($key,$head,86400); } $kk = 'zm_file_' . pathinfo($file,PATHINFO_BASENAME); if(isset($head['Content-Length']) && ($size = intval($head['Content-Length']))){ $kk .= $size; if(is_file($file) && ($size !== filesize($file))){ dump('文件大小不符,重新下载'.$file); unlink($file); return 2; } } if(isset($head['ETag'])){ $t = $kk . md5($head['ETag']); if(Cache::has($t)){ return Cache::get($t); } } if(isset($head['Content-MD5'])){ $t = $kk . md5($head['Content-MD5']); if(Cache::has($t)){ return Cache::get($t); } } } catch (Exception $e) { dump('检查文件失败:',$url,$file,$e); exit; } return 3; } protected function download($downloadurl,$dir,$filename = null) { $num = 1; while($num > 0){ $activeDownloads = $this->aria2->getGlobalStat(); $num = intval($activeDownloads['result']['numWaiting']); if($num > 10){ dump('当前任务过多,等待任务数:',$num); sleep(1); }else{ break; } } $result = $this->aria2->addUri( [$downloadurl], ['dir'=>$dir, 'header'=>[ 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.489.400 QQBrowser/13.7.6351.400', 'referer: https://edu.zmrobo.com/courses', ], 'out'=>$filename] ); } public function getLable($sign = 'null') { $client = new Client(); $result = $client->get("https://edu.zmrobo.com/api/label",[ 'headers'=>[ 'User-Agent'=>'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.489.400 QQBrowser/13.7.6351.400', 'referer'=>'https://edu.zmrobo.com/courses', 'E-Date'=>time(), 'Sign'=>$sign, ] ]); $result = json_decode($result->getBody()->getContents(),true); if($result['code'] == -3){ return $this->getLable($result['sign']); }else{ return $result; } } public function getCurr($label_id,$page,$sign = 'null') { $client = new Client(); $options = [ 'headers'=>[ 'User-Agent'=>'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.489.400 QQBrowser/13.7.6351.400', 'referer'=>'https://edu.zmrobo.com/courses', 'E-Date'=>time(), 'Content-Type'=>'application/json; charset=utf-8', 'Origin'=>'https://edu.zmrobo.com', 'Sign'=>$sign, ], 'body'=>json_encode([ 'label'=>[[$label_id]], 'page'=>$page, ]) ]; $result = $client->post("https://edu.zmrobo.com/api/curriculum/list",$options); $result = json_decode($result->getBody()->getContents(),true); if($result['code'] == -3){ return $this->getCurr($label_id,$page,$result['sign']); }else if($result['code'] == 0){ return $result; }else{ dump($result['msg']); exit(); } } public function getCurrDetails($curr_id,$sign = 'null') { $client = new Client(); $options = [ 'headers'=>[ 'User-Agent'=>'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.489.400 QQBrowser/13.7.6351.400', 'referer'=>'https://edu.zmrobo.com/courses', 'E-Date'=>time(), 'Content-Type'=>'application/json; charset=utf-8', 'Origin'=>'https://edu.zmrobo.com', 'Sign'=>$sign, ], 'body'=>json_encode([ 'id'=>$curr_id, 'user_id'=>$this->user_id, ]) ]; $result = $client->post("https://edu.zmrobo.com/api/curriculum/details",$options); $result = json_decode($result->getBody()->getContents(),true); if($result['code'] == -3){ return $this->getCurrDetails($curr_id,$result['sign']); }else if($result['code'] == 0){ return $result; }else{ dump($result['msg']); exit(); } } public function getClassDetails($curr_id,$sign = 'null') { $client = new Client(); $options = [ 'headers'=>[ 'User-Agent'=>'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.489.400 QQBrowser/13.7.6351.400', 'referer'=>'https://edu.zmrobo.com/courses', 'E-Date'=>time(), 'Content-Type'=>'application/json', 'Origin'=>'https://edu.zmrobo.com', 'Sign'=>$sign, ], 'body'=>json_encode([ 'id'=>$curr_id, 'user_id'=>$this->user_id, 'token'=>"7aa22a83fece93ed3e5a3119b085ced9", ]) ]; $result = $client->post("https://edu.zmrobo.com/api/class/details",$options); $result = json_decode($result->getBody()->getContents(),true); if($result['code'] == -3){ return $this->getClassDetails($curr_id,$result['sign']); }else if($result['code'] == 0){ return $result; }else{ dump($result['msg']); exit(); } } private function savetxt(string $file,string $content) { if(is_file($file)){ unlink($file); } $myfile = fopen($file, "w"); fwrite($myfile, $content); fclose($myfile); // dump('已保存文本内容:'.$file); } }