├── README.md ├── helpers └── helpers.php ├── public └── index.php └── src └── LanzouParser.php /README.md: -------------------------------------------------------------------------------- 1 | # LanZou_API 2 | 3 | 一个用于解析蓝奏云分享链接的 API 服务,支持获取文件信息和下载链接。 4 | 5 | ## 功能特性 6 | 7 | - 支持解析蓝奏云分享链接 8 | - 支持带密码的分享链接 9 | - 支持获取文件详细信息(文件名、大小、上传时间) 10 | - 支持直接获取下载链接 11 | 12 | ## 安装说明 13 | 14 | 1. 克隆项目到本地: 15 | ```bash 16 | git clone https://github.com/5ime/Lanzou_API 17 | ``` 18 | 19 | 2. 确保服务器环境满足以下要求: 20 | - PHP 7.0 或更高版本 21 | - 启用 cURL 扩展 22 | - 支持 HTTPS 请求 23 | 24 | ## 使用方法 25 | 26 | ### 基本使用 27 | 28 | 通过 HTTP GET 请求访问 `public/index.php`,支持以下参数: 29 | 30 | - `url`:蓝奏云分享链接(必填) 31 | - `pwd`:提取码(如果有密码则必填) 32 | - `type`:值为 "down" 时直接跳转下载,否则返回下载链接 33 | 34 | ### 示例请求 35 | 36 | 1. 获取文件信息: 37 | ``` 38 | GET /LanZou_API/public/index.php?url=https://www.lanzoui.com/xxxxxx 39 | ``` 40 | 41 | 2. 带密码的分享链接: 42 | ``` 43 | GET /LanZou_API/public/index.php?url=https://www.lanzoui.com/xxxxxx&pwd=xxxx 44 | ``` 45 | 46 | 3. 直接下载: 47 | ``` 48 | GET /LanZou_API/public/index.php?url=https://www.lanzoui.com/xxxxxx&pwd=xxxx&type=down 49 | ``` 50 | 51 | ### 返回格式 52 | 53 | 成功响应: 54 | ```json 55 | { 56 | "code": 200, 57 | "msg": "解析成功", 58 | "data": { 59 | "name": "文件名", 60 | "size": "文件大小", 61 | "time": "上传时间", 62 | "url": "下载链接" 63 | } 64 | } 65 | ``` 66 | 67 | 错误响应: 68 | ```json 69 | { 70 | "code": 400, 71 | "msg": "错误信息", 72 | "data": null 73 | } 74 | ``` 75 | 76 | ## 注意事项 77 | 78 | 1. 请确保服务器能够正常访问蓝奏云网站 79 | 2. 建议在服务器端设置适当的请求频率限制 80 | 3. 本API仅供学习交流使用,请勿用于商业用途 81 | 4. 使用过程中如遇到问题,请检查: 82 | - 分享链接是否有效 83 | - 提取码是否正确 84 | - 文件是否被删除 85 | - 服务器网络连接是否正常 -------------------------------------------------------------------------------- /helpers/helpers.php: -------------------------------------------------------------------------------- 1 | true, 7 | CURLOPT_FOLLOWLOCATION => true, 8 | CURLOPT_SSL_VERIFYPEER => false, 9 | CURLOPT_TIMEOUT => 10, 10 | CURLOPT_HTTPHEADER => $headers, 11 | ]); 12 | 13 | if (!empty($postData)) { 14 | curl_setopt($ch, CURLOPT_POST, true); 15 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 16 | } 17 | 18 | $result = curl_exec($ch); 19 | if ($result === false) { 20 | $error = curl_error($ch); 21 | curl_close($ch); 22 | return 'Curl Error: ' . $error; 23 | } 24 | curl_close($ch); 25 | return $result; 26 | } 27 | 28 | function getRedirectUrl($url, $referer, $cookie) 29 | { 30 | $headers = [ 31 | 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 32 | 'Accept-Encoding: gzip, deflate', 33 | 'Accept-Language: zh-CN,zh;q=0.9', 34 | 'Cache-Control: no-cache', 35 | 'Connection: keep-alive', 36 | 'Pragma: no-cache', 37 | 'Upgrade-Insecure-Requests: 1', 38 | 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36', 39 | ]; 40 | 41 | $ch = curl_init(); 42 | curl_setopt_array($ch, [ 43 | CURLOPT_URL => $url, 44 | CURLOPT_HTTPHEADER => $headers, 45 | CURLOPT_REFERER => $referer, 46 | CURLOPT_COOKIE => $cookie, 47 | CURLOPT_RETURNTRANSFER => true, 48 | CURLOPT_SSL_VERIFYPEER => false, 49 | CURLOPT_TIMEOUT => 10, 50 | ]); 51 | 52 | curl_exec($ch); 53 | $info = curl_getinfo($ch); 54 | curl_close($ch); 55 | 56 | return $info['redirect_url'] ?? ''; 57 | } 58 | 59 | function response($success, $msg = '', $data = []) 60 | { 61 | $result = [ 62 | 'code' => $success ? 200 : 400, 63 | 'msg' => $success ? ($msg ?: '解析成功') : ($msg ?: '解析失败'), 64 | 'data' => $success ? $data : null 65 | ]; 66 | 67 | die(json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); 68 | } -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | parse(); 35 | 36 | if ($type === 'down') { 37 | if (empty($result['data']['url'])) { 38 | response(false, '获取下载链接失败'); 39 | } 40 | header("Location: {$result['data']['url']}"); 41 | exit; 42 | } 43 | 44 | if (!$result['success']) { 45 | response(false, $result['msg'] ?? '解析失败,请稍后再试'); 46 | } 47 | 48 | response(true, '解析成功', $result['data']); 49 | } catch (Exception $e) { 50 | response(false, '解析过程中发生错误:' . $e->getMessage()); 51 | } -------------------------------------------------------------------------------- /src/LanzouParser.php: -------------------------------------------------------------------------------- 1 | url = $url; 9 | $this->pwd = $pwd; 10 | $this->type = $type; 11 | } 12 | 13 | public function parse() { 14 | $url = $this->formatUrl(); 15 | $headers = $this->getHeaders(); 16 | $content = $this->getPageContent($url, $headers); 17 | 18 | if ($this->isFileDeleted($content)) { 19 | response(false, '文件取消分享了'); 20 | } 21 | 22 | $fileInfo = $this->extractFileInfo($content); 23 | if (!$fileInfo) { 24 | response(false, '解析失败'); 25 | } 26 | 27 | if (strpos($content, 'function down_p(){') !== false) { 28 | if (empty($this->pwd)) { 29 | response(false, '请输入分享密码'); 30 | } 31 | 32 | preg_match("~v3c = '(.*?)';~", $content, $sign); 33 | $sign = $sign[1] ?? ''; 34 | if (strlen($sign) < 82) { 35 | preg_match_all("~sign\'\:\'(.*?)\'~", $content, $sign); 36 | $sign = $sign[1][1] ?? ''; 37 | } 38 | 39 | preg_match("~ajaxm.php\?file=(\d+)~", $content, $ajaxm); 40 | $postData = [ 41 | 'action' => 'downprocess', 42 | 'sign' => $sign, 43 | 'p' => $this->pwd, 44 | 'kd' => 1 45 | ]; 46 | 47 | $headers[] = 'Referer: ' . $url; 48 | $apiUrl = "https://www.lanzoux.com/" . ($ajaxm[0] ?? ''); 49 | $fileInfo['content'] = curlRequest($apiUrl, $postData, $headers); 50 | } else { 51 | preg_match("~ 'downprocess', 60 | 'signs' => '?ctdf', 61 | 'sign' => $sign[1] ?? '', 62 | 'kd' => 1 63 | ]; 64 | 65 | $headers[] = 'Referer: ' . $url; 66 | $apiUrl = "https://www.lanzoux.com/" . ($ajaxm[0][1] ?? $ajaxm[0][0] ?? ''); 67 | $fileInfo['content'] = curlRequest($apiUrl, $postData, $headers); 68 | } 69 | 70 | $downloadUrl = $this->getDownloadUrl($fileInfo); 71 | if (!$downloadUrl) { 72 | response(false, '获取下载链接失败'); 73 | } 74 | 75 | response(true, '', [ 76 | 'name' => $fileInfo['name'], 77 | 'size' => $fileInfo['size'], 78 | 'time' => $fileInfo['time'], 79 | 'url' => $downloadUrl 80 | ]); 81 | } 82 | 83 | private function formatUrl() { 84 | $parts = explode('.com/', $this->url); 85 | return 'https://www.lanzoup.com/' . ($parts[1] ?? ''); 86 | } 87 | 88 | private function getHeaders() { 89 | return [ 90 | 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36' 91 | ]; 92 | } 93 | 94 | private function getPageContent($url, $headers) { 95 | return curlRequest($url, [], $headers); 96 | } 97 | 98 | private function isFileDeleted($content) { 99 | return strpos($content, '文件取消分享了') !== false; 100 | } 101 | 102 | private function extractFileInfo($content) { 103 | preg_match("~文件大小:(.*?)\"~", $content, $size); 104 | preg_match("~n_file_infos\"\>(.*?)\<~", $content, $time); 105 | 106 | if (empty($time[1])) { 107 | preg_match("~上传时间:(.*?)\<~", $content, $time); 108 | } 109 | 110 | $name = $this->extractFileName($content); 111 | 112 | return [ 113 | 'name' => $name, 114 | 'size' => $size[1] ?? '', 115 | 'time' => $time[1] ?? '' 116 | ]; 117 | } 118 | 119 | private function extractFileName($content) { 120 | preg_match("~
(.*?)
~", $content, $name); 121 | if (empty($name[1])) { 122 | preg_match("~(.*?) \-~", $content, $name); 123 | } 124 | return $name[1] ?? ''; 125 | } 126 | 127 | private function getDownloadUrl($fileInfo) { 128 | $response = json_decode($fileInfo['content'], true); 129 | 130 | if ($response['url'] == '0') { 131 | response(false, $response['inf'] ?? '未知错误'); 132 | } 133 | 134 | if (($response['zt'] ?? 0) != 1) { 135 | return false; 136 | } 137 | 138 | 139 | $downloadLink = $response['dom'] . '/file/' . $response['url']; 140 | $finalLink = getRedirectUrl($downloadLink, "https://developer.lanzoug.com", "down_ip=1; expires=Sat, 16-Nov-2019 11:42:54 GMT; path=/; domain=.baidupan.com"); 141 | 142 | if (strpos($finalLink, 'http') === false) { 143 | return $downloadLink; 144 | } 145 | 146 | if (!empty($_GET['n'])) { 147 | preg_match("~(.*?)\?fn=(.*?)\.~", $finalLink, $rename); 148 | return ($rename[1] ?? $finalLink) . $_GET['n']; 149 | } 150 | 151 | return preg_replace('/pid=.*?&/', '', $finalLink); 152 | } 153 | } --------------------------------------------------------------------------------