返回列表 发新帖

【源码分享】小红书之LivePhoto解析php开源代码

  [复制链接]

133

主题

2337

回帖

9106

积分

硕士生

Rank: 6Rank: 6

金币
3836
好评
87
信誉
105
发表于 2026-5-3 16:13:52 来自手机  | 显示全部楼层 | 阅读模式  来自 辽宁
本帖最后由 小奶瓶 于 2026-5-3 21:03 编辑

闲着没事写了一个专门为大红书写的一个获取LivePhoto文件的工具,工具很简陋仅供娱乐请勿当真哦!
不保证所有人都能用,写着玩的,也不要向我反馈问题,因为我是不会修复的。
顺便把我通过DeepSeek写的php开源代码发出来,有能力的自己改改。

php开源代码
  1. <?php
  2. /**
  3. * 小红书笔记解析器
  4. * 通过输入小红书笔记链接,提取并格式化笔记的详细信息
  5. * 包括文本内容、图片(含分辨率)、视频(含分辨率、码率等)信息
  6. */

  7. // 获取用户通过 GET 方法提交的 'url' 参数
  8. // 如果存在 'url' 参数则赋值给 $url,否则设为 null
  9. $url = isset($_GET['url']) ? $_GET['url'] : null;

  10. // 验证 $url 是否为有效的 URL 格式
  11. if ($url && filter_var($url, FILTER_VALIDATE_URL)) {
  12.     // 如果是有效的 URL,则直接使用该 URL 进行后续处理
  13. } else {
  14.     // 如果 $url 不是有效的 URL 格式,尝试从整个 GET 参数字符串中提取 URL
  15.     // 使用正则表达式匹配 http 或 https 开头的完整 URL
  16.     preg_match('/https?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]/', $_GET, $matches);
  17.     // 获取提取到的 URL,如果没提取到则设为 null
  18.     $extracted_url = $matches[0] ?? null;
  19.     if ($extracted_url) {
  20.         // 如果成功提取到 URL,则使用提取的 URL
  21.         $url = $extracted_url;
  22.     } else {
  23.         // 如果既没有有效的输入 URL,也没有提取到 URL,则返回错误信息并终止程序
  24.         die(json_encode(['code' => -1, 'msg' => '请提供有效的 URL 参数或确保 GET 参数中包含可提取的 URL。'], JSON_UNESCAPED_UNICODE));
  25.     }
  26. }

  27. // 检查 URL 是否包含 .com,以进一步确认这是一个可能有效的网址
  28. if ($url && strstr($url, ".com")) {
  29.    
  30.     /**
  31.      * 获取最终的重定向 URL
  32.      * 某些短链接或追踪链接可能会经过多次 301/302 重定向
  33.      * 此函数用于获取重定向后的最终目标 URL
  34.      *
  35.      * @param string $url 原始 URL
  36.      * @return string 最终的重定向 URL(如果没有重定向则返回原始 URL)
  37.      */
  38.     function getRealUrl($url) {
  39.         // 获取 URL 的所有响应头信息
  40.         // 第二个参数 1 表示以关联数组形式返回,便于处理多个同名 header
  41.         $headers = get_headers($url, 1);
  42.         // 定义需要处理的重定向状态码数组(301 永久重定向,302 临时重定向)
  43.         $redirectCodes = ['301', '302'];
  44.         // 遍历重定向状态码数组,检查响应头中是否包含这些状态码
  45.         foreach ($redirectCodes as $code) {
  46.             // 检查响应头的第一行是否包含重定向状态码
  47.             if (strpos($headers[0], $code) !== false) {
  48.                 // 如果 'Location' 头信息是一个数组(表示存在多次重定向)
  49.                 if (is_array($headers['Location'])) {
  50.                     // 返回最后一个重定向的 URL(即最终目标地址)
  51.                     return end($headers['Location']);
  52.                 } else {
  53.                     // 如果 'Location' 头信息是字符串(单次重定向),直接返回该 URL
  54.                     return $headers['Location'];
  55.                 }
  56.             }
  57.         }
  58.         // 如果没有检测到任何重定向,返回原始 URL
  59.         return $url;
  60.     }

  61.     // 调用函数获取最终的重定向 URL,更新 $url 变量
  62.     $url = getRealUrl($url);

  63.     // 设置模拟电脑端 Chrome 浏览器的用户代理字符串
  64.     // 用于避免被目标网站识别为爬虫或被重定向到移动版页面
  65.     $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36';

  66.     // 设置 HTTP 响应头,声明返回的内容类型为 JSON 格式
  67.     header('Content-type:text/json');

  68.     // 初始化 cURL 会话,用于发起 HTTP 请求
  69.     $ch = curl_init();
  70.     // 设置要请求的 URL
  71.     curl_setopt($ch, CURLOPT_URL, $url);
  72.     // 设置为不返回响应头信息(只需要响应体)
  73.     curl_setopt($ch, CURLOPT_HEADER, false);
  74.     // 将 curl_exec() 获取的信息以字符串形式返回,而不是直接输出到浏览器
  75.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  76.     // 禁用 SSL 证书验证(避免因证书问题导致请求失败)
  77.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  78.     // 不验证 SSL 主机名(与上一条配合使用,跳过 SSL 验证)
  79.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  80.     // 自动处理所有编码类型(如 gzip、deflate),设置空字符串表示支持所有编码
  81.     curl_setopt($ch, CURLOPT_ENCODING, '');
  82.     // 设置用户代理,模拟浏览器访问
  83.     curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
  84.     // 启用自动跟踪重定向(跟随 301/302 跳转)
  85.     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

  86.     /**
  87.      * 解码 URL 中的 Unicode 转义字符
  88.      * 将 \uXXXX 格式的 Unicode 编码转换为对应的 UTF-8 字符
  89.      * 例如:\u4e2d\u6587 会被转换为 "中文"
  90.      *
  91.      * @param string $s 包含 Unicode 转义字符的字符串
  92.      * @return string 解码后的 UTF-8 字符串
  93.      */
  94.     function decodeURL($s) {
  95.         return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($matches) {
  96.             // 将十六进制的 Unicode 码点打包成二进制数据
  97.             // 然后转换为 UTF-8 编码的字符
  98.             return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
  99.         }, $s);
  100.     }

  101.     // 执行 cURL 请求并获取响应数据
  102.     // 同时对响应内容中的 Unicode 转义字符进行解码
  103.     $data = decodeURL(curl_exec($ch));
  104.     // 关闭 cURL 会话,释放系统资源
  105.     curl_close($ch);

  106.     /**
  107.      * 提取两个字符串之间的内容
  108.      * 用于从 HTML 或 JavaScript 代码中截取特定部分的数据
  109.      *
  110.      * @param string $content 原始内容字符串
  111.      * @param string $start 起始标记字符串
  112.      * @param string $end 结束标记字符串
  113.      * @return string 两个标记之间的内容,如果未找到则返回空字符串
  114.      */
  115.     function getBetween($content, $start, $end) {
  116.         // 查找起始字符串在内容中的位置
  117.         $posStart = strpos($content, $start);
  118.         if ($posStart !== false) {
  119.             // 从起始字符串结束位置开始,查找结束字符串的位置
  120.             $posEnd = strpos($content, $end, $posStart + strlen($start));
  121.             if ($posEnd !== false) {
  122.                 // 截取并返回两个位置之间的内容
  123.                 return substr($content, $posStart + strlen($start), $posEnd - $posStart - strlen($start));
  124.             }
  125.         }
  126.         // 如果未找到起始或结束标记,返回空字符串
  127.         return '';
  128.     }

  129.     // 检查是否成功获取到网页数据
  130.     if ($data) {
  131.         // 第一步提取:从页面 JavaScript 中提取 __INITIAL_STATE__ 对象
  132.         // 小红书将初始数据存储在 window.__INITIAL_STATE__ 变量中
  133.         $start = 'window.__INITIAL_STATE__=';
  134.         $end = '</script>';
  135.         $data = getBetween($data, $start, $end);

  136.         // 第二步提取:从初始化状态中提取笔记数据的起始部分
  137.         // 笔记数据位于 "note": 和 ,"nioStore 之间
  138.         $start = '"note":';
  139.         $end = ',"nioStore';
  140.         $data = getBetween($data, $start, $end);

  141.         // 第三步提取:精确提取笔记对象的完整 JSON 数据
  142.         // 从 "note": 开始,到第一个完整的笔记对象结束
  143.         $start = '"note":';
  144.         $end = '}},"serverRequestInfo';
  145.         $jsonContent = getBetween($data, $start, $end);

  146.         // 检查是否成功提取到 JSON 内容
  147.         if (isset($jsonContent)) {
  148.             // 将 JSON 字符串解析为 PHP 关联数组
  149.             $json = json_decode($jsonContent, true);

  150.             // 如果 JSON 解析失败,返回错误信息
  151.             if (!$json) {
  152.                 exit(json_encode(['code' => -1, 'msg' => '获取详细信息失败'], JSON_UNESCAPED_UNICODE));
  153.             }

  154.             // 构建统一的输出数据结构
  155.             // 包含状态码、提示信息和格式化后的笔记数据
  156.             $result = [
  157.                 'code' => 0,        // 状态码:0 表示成功
  158.                 'msg' => '成功',     // 提示信息
  159.                 'data' => [
  160.                     // 笔记 ID,用于唯一标识一条笔记
  161.                     'noteId' => $json['noteId'] ?? '',
  162.                     // 笔记标题
  163.                     'title' => $json['title'] ?? '',
  164.                     // 笔记正文描述
  165.                     'desc' => $json['desc'] ?? '',
  166.                     // 笔记类型:normal(图文)或 video(视频)
  167.                     'type' => $json['type'] ?? '',
  168.                     // 发布时间(将毫秒时间戳转换为可读的日期时间格式)
  169.                     'time' => isset($json['time']) ? date('Y-m-d H:i:s', $json['time'] / 1000) : '',
  170.                     // 最后更新时间
  171.                     'lastUpdateTime' => isset($json['lastUpdateTime']) ? date('Y-m-d H:i:s', $json['lastUpdateTime'] / 1000) : '',
  172.                     // IP 属地(发布者所在地区)
  173.                     'ipLocation' => $json['ipLocation'] ?? '',
  174.                     // 用户信息
  175.                     'user' => [
  176.                         'userId' => $json['user']['userId'] ?? '',       // 用户 ID
  177.                         'nickname' => $json['user']['nickname'] ?? '',    // 用户昵称
  178.                         'avatar' => $json['user']['avatar'] ?? ''         // 用户头像 URL
  179.                     ],
  180.                     // 互动信息(点赞、收藏、评论、分享数量)
  181.                     'interactInfo' => [
  182.                         'likedCount' => $json['interactInfo']['likedCount'] ?? '',          // 点赞数
  183.                         'collectedCount' => $json['interactInfo']['collectedCount'] ?? '',  // 收藏数
  184.                         'commentCount' => $json['interactInfo']['commentCount'] ?? '',      // 评论数
  185.                         'shareCount' => $json['interactInfo']['shareCount'] ?? ''           // 分享数
  186.                     ],
  187.                     // 标签列表(提取标签名称组成简单数组)
  188.                     'tagList' => array_map(function($tag) {
  189.                         return $tag['name'] ?? '';
  190.                     }, $json['tagList'] ?? []),
  191.                     // 图片列表(包含分辨率、视频流等信息)
  192.                     'imageList' => [],
  193.                     // 视频信息(如果是视频笔记)
  194.                     'videoInfo' => null
  195.                 ]
  196.             ];

  197.             // ========== 处理图片列表 ==========
  198.             // 检查是否存在图片列表数据
  199.             if (isset($json['imageList']) && is_array($json['imageList'])) {
  200.                 // 遍历每张图片,提取详细信息
  201.                 foreach ($json['imageList'] as $image) {
  202.                     // 构建单张图片的信息数组
  203.                     $imageInfo = [
  204.                         // 图片宽度(像素)
  205.                         'width' => $image['width'] ?? 0,
  206.                         // 图片高度(像素)
  207.                         'height' => $image['height'] ?? 0,
  208.                         // 图片分辨率(格式:宽x高,如 1920x2560)
  209.                         'resolution' => ($image['width'] ?? 0) . 'x' . ($image['height'] ?? 0),
  210.                         // 是否为 Live Photo(实况照片,包含短视频)
  211.                         'livePhoto' => $image['livePhoto'] ?? false,
  212.                         // 默认显示的图片 URL
  213.                         'urlDefault' => $image['urlDefault'] ?? '',
  214.                         // 预览图片 URL
  215.                         'urlPre' => $image['urlPre'] ?? '',
  216.                         // 不同场景下的图片 URL 列表(如预览、默认等)
  217.                         'infoList' => []
  218.                     ];

  219.                     // 处理不同场景的图片 URL
  220.                     // WB_PRV: 预览场景,WB_DFT: 默认场景
  221.                     if (isset($image['infoList']) && is_array($image['infoList'])) {
  222.                         foreach ($image['infoList'] as $info) {
  223.                             // 以场景类型作为键名,URL 作为值
  224.                             // 例如:'WB_PRV' => 'http://...'
  225.                             $imageInfo['infoList'][$info['imageScene']] = $info['url'] ?? '';
  226.                         }
  227.                     }

  228.                     // 处理 Live Photo 的视频流数据
  229.                     // Live Photo 包含短视频,videoCodec 信息存储在不同编解码格式的数组中
  230.                     if (isset($image['stream']) && !empty($image['stream'])) {
  231.                         $imageInfo['stream'] = [];
  232.                         // 遍历支持的视频编解码格式
  233.                         // h264: 最常见的视频编码格式
  234.                         // h265: 高效视频编码(HEVC)
  235.                         // h266: 多功能视频编码(VVC)
  236.                         // av1: 开放视频编码格式
  237.                         foreach (['h264', 'h265', 'h266', 'av1'] as $codec) {
  238.                             // 如果该编解码格式有可用视频流
  239.                             if (isset($image['stream'][$codec]) && !empty($image['stream'][$codec])) {
  240.                                 // 提取每个视频流的 URL 信息
  241.                                 $imageInfo['stream'][$codec] = array_map(function($item) {
  242.                                     return [
  243.                                         // 主视频 URL
  244.                                         'masterUrl' => $item['masterUrl'] ?? '',
  245.                                         // 备用视频 URL 列表(用于容错)
  246.                                         'backupUrls' => $item['backupUrls'] ?? []
  247.                                     ];
  248.                                 }, $image['stream'][$codec]);
  249.                             }
  250.                         }
  251.                     }

  252.                     // 将处理好的图片信息添加到图片列表
  253.                     $result['data']['imageList'][] = $imageInfo;
  254.                 }
  255.             }

  256.             // ========== 处理视频信息 ==========
  257.             // 检查是否存在视频数据(视频笔记才有此字段)
  258.             if (isset($json['video']) && !empty($json['video'])) {
  259.                 // 初始化视频信息数组
  260.                 $videoInfo = [
  261.                     // 视频时长(毫秒)
  262.                     'duration' => $json['video']['capa']['duration'] ?? 0,
  263.                     // 视频媒体流列表(不同分辨率和编解码格式)
  264.                     'media' => []
  265.                 ];

  266.                 // 处理视频媒体流数据
  267.                 if (isset($json['video']['media']['stream'])) {
  268.                     // 遍历所有支持的视频编解码格式
  269.                     foreach (['h264', 'h265', 'h266', 'av1'] as $codec) {
  270.                         // 如果该编解码格式有可用视频流
  271.                         if (isset($json['video']['media']['stream'][$codec]) && !empty($json['video']['media']['stream'][$codec])) {
  272.                             // 遍历该编解码格式下的所有视频流(可能有不同分辨率)
  273.                             foreach ($json['video']['media']['stream'][$codec] as $streamItem) {
  274.                                 // 构建视频流详细信息数组
  275.                                 $videoInfo['media'][] = [
  276.                                     // 视频编解码器类型
  277.                                     'codec' => $codec,
  278.                                     // 视频分辨率(格式:宽x高,如 1280x720)
  279.                                     'resolution' => ($streamItem['width'] ?? 0) . 'x' . ($streamItem['height'] ?? 0),
  280.                                     // 视频宽度(像素)
  281.                                     'width' => $streamItem['width'] ?? 0,
  282.                                     // 视频高度(像素)
  283.                                     'height' => $streamItem['height'] ?? 0,
  284.                                     // 视频流时长(毫秒)
  285.                                     'duration' => $streamItem['duration'] ?? 0,
  286.                                     // 视频帧率(FPS,每秒帧数)
  287.                                     'fps' => $streamItem['fps'] ?? 0,
  288.                                     // 平均比特率(bps,比特每秒)
  289.                                     'avgBitrate' => $streamItem['avgBitrate'] ?? 0,
  290.                                     // 视频文件格式(如 mp4)
  291.                                     'format' => $streamItem['format'] ?? '',
  292.                                     // 视频质量类型(如 HD 表示高清)
  293.                                     'qualityType' => $streamItem['qualityType'] ?? '',
  294.                                     // 主视频播放 URL
  295.                                     'masterUrl' => $streamItem['masterUrl'] ?? '',
  296.                                     // 备用视频播放 URL 列表
  297.                                     'backupUrls' => $streamItem['backupUrls'] ?? []
  298.                                 ];
  299.                             }
  300.                         }
  301.                     }
  302.                 }

  303.                 // 将处理好的视频信息赋值给结果数组
  304.                 $result['data']['videoInfo'] = $videoInfo;
  305.             }

  306.             // 输出最终处理结果
  307.             // JSON_PRETTY_PRINT: 格式化输出,便于阅读
  308.             // JSON_UNESCAPED_UNICODE: 不转义 Unicode 字符,确保中文正常显示
  309.             // JSON_UNESCAPED_SLASHES: 不转义斜杠,保持 URL 可读性
  310.             exit(json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
  311.         } else {
  312.             // JSON 内容提取失败,返回解析错误
  313.             exit(json_encode(['code' => -1, 'msg' => '解析出错!'], JSON_UNESCAPED_UNICODE));
  314.         }
  315.     } else {
  316.         // 网页数据获取失败,返回提示信息
  317.         exit(json_encode(['code' => -1, 'msg' => '请输入网址'], JSON_UNESCAPED_UNICODE));
  318.     }
  319. }
  320. ?>
复制代码


下载地址:
https://www.lanzouu.com/b00wnhiruj

此工具仅供学习参考请勿用于商业或非法用途哦,下载后请于二十四小时内删除,谢谢合作。

回复

使用道具 举报

311

主题

198

回帖

8625

积分

硕士生

Rank: 6Rank: 6

金币
1169
好评
11
信誉
100
发表于 2026-5-3 16:14:48 | 显示全部楼层  来自 广东
看看隐藏
回复

使用道具 举报

34

主题

1169

回帖

4894

积分

大学生

Rank: 5Rank: 5

金币
1822
好评
5
信誉
100

MT论坛最佳新人MT论坛新人

发表于 2026-5-3 16:26:48 来自手机  | 显示全部楼层  来自 云南
大佬分享必赞!!!!
回复

使用道具 举报

20

主题

1万

回帖

2万

积分

博士后

Rank: 8Rank: 8

金币
2647
好评
9
信誉
96

考神

发表于 2026-5-3 16:27:15 来自手机  | 显示全部楼层  来自 河北
回复可见
回复

使用道具 举报

87

主题

2597

回帖

8603

积分

硕士生

逆向小白

Rank: 6Rank: 6

金币
2680
好评
55
信誉
168

考神MT论坛新人MT论坛帅哥MT论坛最佳新人MT论坛活跃会员

发表于 2026-5-3 16:34:51 来自手机  | 显示全部楼层  来自 江西
看看隐藏
回复

使用道具 举报

10

主题

7203

回帖

1万

积分

博士生

Rank: 7Rank: 7Rank: 7

金币
5145
好评
1
信誉
91

MT论坛最佳新人考神

发表于 2026-5-3 16:35:12 来自手机  | 显示全部楼层  来自 湖北
看看隐藏
回复

使用道具 举报

9

主题

1985

回帖

7098

积分

硕士生

Rank: 6Rank: 6

金币
3068
好评
4
信誉
101

MT论坛最佳新人MT论坛帅哥考神MT论坛新人

发表于 2026-5-3 16:44:19 来自手机  | 显示全部楼层  来自 浙江
看看
回复

使用道具 举报

2

主题

4507

回帖

1万

积分

禁止访问

iKUN

金币
1214
好评
16
信誉
111
发表于 2026-5-3 16:50:18 来自手机  | 显示全部楼层  来自 广西
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

6

主题

828

回帖

1806

积分

高中生

Rank: 4

金币
865
好评
0
信誉
100
发表于 2026-5-3 16:54:17 来自手机  | 显示全部楼层  来自 山东
看看隐藏
回复

使用道具 举报

0

主题

2972

回帖

6911

积分

硕士生

Rank: 6Rank: 6

金币
3330
好评
0
信誉
100

MT论坛新人考神MT论坛帅哥

发表于 2026-5-3 16:56:49 来自手机  | 显示全部楼层  来自 浙江
感谢分享
回复

使用道具 举报

10

主题

3706

回帖

1万

积分

博士生

Rank: 7Rank: 7Rank: 7

金币
5022
好评
2
信誉
112

MT论坛最佳新人考神MT论坛帅哥

发表于 2026-5-3 17:00:36 来自手机  | 显示全部楼层  来自 福建
感谢分享
回复

使用道具 举报

2

主题

2091

回帖

5444

积分

硕士生

逆向新手

Rank: 6Rank: 6

金币
1691
好评
0
信誉
93
发表于 2026-5-3 17:14:34 来自手机  | 显示全部楼层  来自 海南
看看
回复

使用道具 举报

0

主题

52

回帖

224

积分

小学生

Rank: 2

金币
82
好评
0
信誉
100
发表于 2026-5-3 17:19:29 来自手机  | 显示全部楼层  来自 河北
......
回复

使用道具 举报

19

主题

1018

回帖

3448

积分

大学生

王鹏

Rank: 5Rank: 5

金币
1053
好评
1
信誉
100

MT论坛最佳新人考神MT论坛帅哥MT论坛新人

QQ
发表于 2026-5-3 17:35:27 来自手机  | 显示全部楼层  来自 陕西
看看隐藏
回复

使用道具 举报

2

主题

1743

回帖

5695

积分

硕士生

Rank: 6Rank: 6

金币
1132
好评
0
信誉
100

考神

发表于 2026-5-3 17:41:44 来自手机  | 显示全部楼层  来自 河北
看看
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表