硕士生
 
- 金币
- 3836
- 好评
- 87
- 信誉
- 105
|
本帖最后由 小奶瓶 于 2026-5-3 21:03 编辑
闲着没事写了一个专门为大红书写的一个获取LivePhoto文件的工具,工具很简陋仅供娱乐请勿当真哦!
不保证所有人都能用,写着玩的,也不要向我反馈问题,因为我是不会修复的。
顺便把我通过DeepSeek写的php开源代码发出来,有能力的自己改改。
php开源代码
- <?php
- /**
- * 小红书笔记解析器
- * 通过输入小红书笔记链接,提取并格式化笔记的详细信息
- * 包括文本内容、图片(含分辨率)、视频(含分辨率、码率等)信息
- */
- // 获取用户通过 GET 方法提交的 'url' 参数
- // 如果存在 'url' 参数则赋值给 $url,否则设为 null
- $url = isset($_GET['url']) ? $_GET['url'] : null;
- // 验证 $url 是否为有效的 URL 格式
- if ($url && filter_var($url, FILTER_VALIDATE_URL)) {
- // 如果是有效的 URL,则直接使用该 URL 进行后续处理
- } else {
- // 如果 $url 不是有效的 URL 格式,尝试从整个 GET 参数字符串中提取 URL
- // 使用正则表达式匹配 http 或 https 开头的完整 URL
- preg_match('/https?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]/', $_GET, $matches);
- // 获取提取到的 URL,如果没提取到则设为 null
- $extracted_url = $matches[0] ?? null;
- if ($extracted_url) {
- // 如果成功提取到 URL,则使用提取的 URL
- $url = $extracted_url;
- } else {
- // 如果既没有有效的输入 URL,也没有提取到 URL,则返回错误信息并终止程序
- die(json_encode(['code' => -1, 'msg' => '请提供有效的 URL 参数或确保 GET 参数中包含可提取的 URL。'], JSON_UNESCAPED_UNICODE));
- }
- }
- // 检查 URL 是否包含 .com,以进一步确认这是一个可能有效的网址
- if ($url && strstr($url, ".com")) {
-
- /**
- * 获取最终的重定向 URL
- * 某些短链接或追踪链接可能会经过多次 301/302 重定向
- * 此函数用于获取重定向后的最终目标 URL
- *
- * @param string $url 原始 URL
- * @return string 最终的重定向 URL(如果没有重定向则返回原始 URL)
- */
- function getRealUrl($url) {
- // 获取 URL 的所有响应头信息
- // 第二个参数 1 表示以关联数组形式返回,便于处理多个同名 header
- $headers = get_headers($url, 1);
- // 定义需要处理的重定向状态码数组(301 永久重定向,302 临时重定向)
- $redirectCodes = ['301', '302'];
- // 遍历重定向状态码数组,检查响应头中是否包含这些状态码
- foreach ($redirectCodes as $code) {
- // 检查响应头的第一行是否包含重定向状态码
- if (strpos($headers[0], $code) !== false) {
- // 如果 'Location' 头信息是一个数组(表示存在多次重定向)
- if (is_array($headers['Location'])) {
- // 返回最后一个重定向的 URL(即最终目标地址)
- return end($headers['Location']);
- } else {
- // 如果 'Location' 头信息是字符串(单次重定向),直接返回该 URL
- return $headers['Location'];
- }
- }
- }
- // 如果没有检测到任何重定向,返回原始 URL
- return $url;
- }
- // 调用函数获取最终的重定向 URL,更新 $url 变量
- $url = getRealUrl($url);
- // 设置模拟电脑端 Chrome 浏览器的用户代理字符串
- // 用于避免被目标网站识别为爬虫或被重定向到移动版页面
- $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36';
- // 设置 HTTP 响应头,声明返回的内容类型为 JSON 格式
- header('Content-type:text/json');
- // 初始化 cURL 会话,用于发起 HTTP 请求
- $ch = curl_init();
- // 设置要请求的 URL
- curl_setopt($ch, CURLOPT_URL, $url);
- // 设置为不返回响应头信息(只需要响应体)
- curl_setopt($ch, CURLOPT_HEADER, false);
- // 将 curl_exec() 获取的信息以字符串形式返回,而不是直接输出到浏览器
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- // 禁用 SSL 证书验证(避免因证书问题导致请求失败)
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- // 不验证 SSL 主机名(与上一条配合使用,跳过 SSL 验证)
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
- // 自动处理所有编码类型(如 gzip、deflate),设置空字符串表示支持所有编码
- curl_setopt($ch, CURLOPT_ENCODING, '');
- // 设置用户代理,模拟浏览器访问
- curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
- // 启用自动跟踪重定向(跟随 301/302 跳转)
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- /**
- * 解码 URL 中的 Unicode 转义字符
- * 将 \uXXXX 格式的 Unicode 编码转换为对应的 UTF-8 字符
- * 例如:\u4e2d\u6587 会被转换为 "中文"
- *
- * @param string $s 包含 Unicode 转义字符的字符串
- * @return string 解码后的 UTF-8 字符串
- */
- function decodeURL($s) {
- return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($matches) {
- // 将十六进制的 Unicode 码点打包成二进制数据
- // 然后转换为 UTF-8 编码的字符
- return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
- }, $s);
- }
- // 执行 cURL 请求并获取响应数据
- // 同时对响应内容中的 Unicode 转义字符进行解码
- $data = decodeURL(curl_exec($ch));
- // 关闭 cURL 会话,释放系统资源
- curl_close($ch);
- /**
- * 提取两个字符串之间的内容
- * 用于从 HTML 或 JavaScript 代码中截取特定部分的数据
- *
- * @param string $content 原始内容字符串
- * @param string $start 起始标记字符串
- * @param string $end 结束标记字符串
- * @return string 两个标记之间的内容,如果未找到则返回空字符串
- */
- function getBetween($content, $start, $end) {
- // 查找起始字符串在内容中的位置
- $posStart = strpos($content, $start);
- if ($posStart !== false) {
- // 从起始字符串结束位置开始,查找结束字符串的位置
- $posEnd = strpos($content, $end, $posStart + strlen($start));
- if ($posEnd !== false) {
- // 截取并返回两个位置之间的内容
- return substr($content, $posStart + strlen($start), $posEnd - $posStart - strlen($start));
- }
- }
- // 如果未找到起始或结束标记,返回空字符串
- return '';
- }
- // 检查是否成功获取到网页数据
- if ($data) {
- // 第一步提取:从页面 JavaScript 中提取 __INITIAL_STATE__ 对象
- // 小红书将初始数据存储在 window.__INITIAL_STATE__ 变量中
- $start = 'window.__INITIAL_STATE__=';
- $end = '</script>';
- $data = getBetween($data, $start, $end);
- // 第二步提取:从初始化状态中提取笔记数据的起始部分
- // 笔记数据位于 "note": 和 ,"nioStore 之间
- $start = '"note":';
- $end = ',"nioStore';
- $data = getBetween($data, $start, $end);
- // 第三步提取:精确提取笔记对象的完整 JSON 数据
- // 从 "note": 开始,到第一个完整的笔记对象结束
- $start = '"note":';
- $end = '}},"serverRequestInfo';
- $jsonContent = getBetween($data, $start, $end);
- // 检查是否成功提取到 JSON 内容
- if (isset($jsonContent)) {
- // 将 JSON 字符串解析为 PHP 关联数组
- $json = json_decode($jsonContent, true);
- // 如果 JSON 解析失败,返回错误信息
- if (!$json) {
- exit(json_encode(['code' => -1, 'msg' => '获取详细信息失败'], JSON_UNESCAPED_UNICODE));
- }
- // 构建统一的输出数据结构
- // 包含状态码、提示信息和格式化后的笔记数据
- $result = [
- 'code' => 0, // 状态码:0 表示成功
- 'msg' => '成功', // 提示信息
- 'data' => [
- // 笔记 ID,用于唯一标识一条笔记
- 'noteId' => $json['noteId'] ?? '',
- // 笔记标题
- 'title' => $json['title'] ?? '',
- // 笔记正文描述
- 'desc' => $json['desc'] ?? '',
- // 笔记类型:normal(图文)或 video(视频)
- 'type' => $json['type'] ?? '',
- // 发布时间(将毫秒时间戳转换为可读的日期时间格式)
- 'time' => isset($json['time']) ? date('Y-m-d H:i:s', $json['time'] / 1000) : '',
- // 最后更新时间
- 'lastUpdateTime' => isset($json['lastUpdateTime']) ? date('Y-m-d H:i:s', $json['lastUpdateTime'] / 1000) : '',
- // IP 属地(发布者所在地区)
- 'ipLocation' => $json['ipLocation'] ?? '',
- // 用户信息
- 'user' => [
- 'userId' => $json['user']['userId'] ?? '', // 用户 ID
- 'nickname' => $json['user']['nickname'] ?? '', // 用户昵称
- 'avatar' => $json['user']['avatar'] ?? '' // 用户头像 URL
- ],
- // 互动信息(点赞、收藏、评论、分享数量)
- 'interactInfo' => [
- 'likedCount' => $json['interactInfo']['likedCount'] ?? '', // 点赞数
- 'collectedCount' => $json['interactInfo']['collectedCount'] ?? '', // 收藏数
- 'commentCount' => $json['interactInfo']['commentCount'] ?? '', // 评论数
- 'shareCount' => $json['interactInfo']['shareCount'] ?? '' // 分享数
- ],
- // 标签列表(提取标签名称组成简单数组)
- 'tagList' => array_map(function($tag) {
- return $tag['name'] ?? '';
- }, $json['tagList'] ?? []),
- // 图片列表(包含分辨率、视频流等信息)
- 'imageList' => [],
- // 视频信息(如果是视频笔记)
- 'videoInfo' => null
- ]
- ];
- // ========== 处理图片列表 ==========
- // 检查是否存在图片列表数据
- if (isset($json['imageList']) && is_array($json['imageList'])) {
- // 遍历每张图片,提取详细信息
- foreach ($json['imageList'] as $image) {
- // 构建单张图片的信息数组
- $imageInfo = [
- // 图片宽度(像素)
- 'width' => $image['width'] ?? 0,
- // 图片高度(像素)
- 'height' => $image['height'] ?? 0,
- // 图片分辨率(格式:宽x高,如 1920x2560)
- 'resolution' => ($image['width'] ?? 0) . 'x' . ($image['height'] ?? 0),
- // 是否为 Live Photo(实况照片,包含短视频)
- 'livePhoto' => $image['livePhoto'] ?? false,
- // 默认显示的图片 URL
- 'urlDefault' => $image['urlDefault'] ?? '',
- // 预览图片 URL
- 'urlPre' => $image['urlPre'] ?? '',
- // 不同场景下的图片 URL 列表(如预览、默认等)
- 'infoList' => []
- ];
- // 处理不同场景的图片 URL
- // WB_PRV: 预览场景,WB_DFT: 默认场景
- if (isset($image['infoList']) && is_array($image['infoList'])) {
- foreach ($image['infoList'] as $info) {
- // 以场景类型作为键名,URL 作为值
- // 例如:'WB_PRV' => 'http://...'
- $imageInfo['infoList'][$info['imageScene']] = $info['url'] ?? '';
- }
- }
- // 处理 Live Photo 的视频流数据
- // Live Photo 包含短视频,videoCodec 信息存储在不同编解码格式的数组中
- if (isset($image['stream']) && !empty($image['stream'])) {
- $imageInfo['stream'] = [];
- // 遍历支持的视频编解码格式
- // h264: 最常见的视频编码格式
- // h265: 高效视频编码(HEVC)
- // h266: 多功能视频编码(VVC)
- // av1: 开放视频编码格式
- foreach (['h264', 'h265', 'h266', 'av1'] as $codec) {
- // 如果该编解码格式有可用视频流
- if (isset($image['stream'][$codec]) && !empty($image['stream'][$codec])) {
- // 提取每个视频流的 URL 信息
- $imageInfo['stream'][$codec] = array_map(function($item) {
- return [
- // 主视频 URL
- 'masterUrl' => $item['masterUrl'] ?? '',
- // 备用视频 URL 列表(用于容错)
- 'backupUrls' => $item['backupUrls'] ?? []
- ];
- }, $image['stream'][$codec]);
- }
- }
- }
- // 将处理好的图片信息添加到图片列表
- $result['data']['imageList'][] = $imageInfo;
- }
- }
- // ========== 处理视频信息 ==========
- // 检查是否存在视频数据(视频笔记才有此字段)
- if (isset($json['video']) && !empty($json['video'])) {
- // 初始化视频信息数组
- $videoInfo = [
- // 视频时长(毫秒)
- 'duration' => $json['video']['capa']['duration'] ?? 0,
- // 视频媒体流列表(不同分辨率和编解码格式)
- 'media' => []
- ];
- // 处理视频媒体流数据
- if (isset($json['video']['media']['stream'])) {
- // 遍历所有支持的视频编解码格式
- foreach (['h264', 'h265', 'h266', 'av1'] as $codec) {
- // 如果该编解码格式有可用视频流
- if (isset($json['video']['media']['stream'][$codec]) && !empty($json['video']['media']['stream'][$codec])) {
- // 遍历该编解码格式下的所有视频流(可能有不同分辨率)
- foreach ($json['video']['media']['stream'][$codec] as $streamItem) {
- // 构建视频流详细信息数组
- $videoInfo['media'][] = [
- // 视频编解码器类型
- 'codec' => $codec,
- // 视频分辨率(格式:宽x高,如 1280x720)
- 'resolution' => ($streamItem['width'] ?? 0) . 'x' . ($streamItem['height'] ?? 0),
- // 视频宽度(像素)
- 'width' => $streamItem['width'] ?? 0,
- // 视频高度(像素)
- 'height' => $streamItem['height'] ?? 0,
- // 视频流时长(毫秒)
- 'duration' => $streamItem['duration'] ?? 0,
- // 视频帧率(FPS,每秒帧数)
- 'fps' => $streamItem['fps'] ?? 0,
- // 平均比特率(bps,比特每秒)
- 'avgBitrate' => $streamItem['avgBitrate'] ?? 0,
- // 视频文件格式(如 mp4)
- 'format' => $streamItem['format'] ?? '',
- // 视频质量类型(如 HD 表示高清)
- 'qualityType' => $streamItem['qualityType'] ?? '',
- // 主视频播放 URL
- 'masterUrl' => $streamItem['masterUrl'] ?? '',
- // 备用视频播放 URL 列表
- 'backupUrls' => $streamItem['backupUrls'] ?? []
- ];
- }
- }
- }
- }
- // 将处理好的视频信息赋值给结果数组
- $result['data']['videoInfo'] = $videoInfo;
- }
- // 输出最终处理结果
- // JSON_PRETTY_PRINT: 格式化输出,便于阅读
- // JSON_UNESCAPED_UNICODE: 不转义 Unicode 字符,确保中文正常显示
- // JSON_UNESCAPED_SLASHES: 不转义斜杠,保持 URL 可读性
- exit(json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
- } else {
- // JSON 内容提取失败,返回解析错误
- exit(json_encode(['code' => -1, 'msg' => '解析出错!'], JSON_UNESCAPED_UNICODE));
- }
- } else {
- // 网页数据获取失败,返回提示信息
- exit(json_encode(['code' => -1, 'msg' => '请输入网址'], JSON_UNESCAPED_UNICODE));
- }
- }
- ?>
复制代码
下载地址:
https://www.lanzouu.com/b00wnhiruj
此工具仅供学习参考请勿用于商业或非法用途哦,下载后请于二十四小时内删除,谢谢合作。
|
|