良有益 发表于 2024-12-3 17:26:21

多功能阅读rss模板

本帖最后由 良有益 于 2024-12-4 10:37 编辑

使用通义写的多功能订阅源模板,适合看多页图片,视频,文本,会的修改几个地方即可使用,此模板使用xxx.biz制作,复制进去即可使用,
通过多重方式查找视频。会改的大神可以自行修改。还有不完善的,主要针对秀人之类的多页多图、网页有视频的(有些在标签获取不到script内)。
以下是功能
1.通过获取页码拼接网页,如何提取每个网页
2.标签获取视频地址,
3.正则表达式正常视频地址,
4.正则表达式匹配拼接非正常视频地址,可设置后缀添加,
5.可设置多个播放域名,适合某草,
6.标签获取图片,
7.标签获取文本。


<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
body{font-family:Arial,sans-serif;display:flex;flex-direction:column;align-items:center;min-height:100vh;margin:0;padding:10px;box-sizing:border-box}
#loading,h3,h5{text-align:center;margin:20px 0}
#description,#text,#urls,#video-url{white-space:pre-wrap;word-break:break-all;max-width:100%;margin:0 auto;text-align:left}
#video-source-select{width:calc(100% - 22px);padding:10px;font-size:20px;border:1px solid #ccc;border-radius:5px;margin-bottom:20px;box-sizing:border-box}
#images img,#video-container video{max-width:100%;height:auto;margin-bottom:5px;display:block}
#text{margin-top:20px}
#controls{width:80%;margin:20px auto;text-align:center}
#fullscreen-btn,#play-pause-btn{cursor:pointer;margin:0 10px}
#volume-slider{width:100px}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
<!-- 提取页面标题 -->
<h3 id="title">{{@@.title@text||h1@text}}</h3>
<!-- 提取简介 -->
<p id="description">{{@@class.entry-meta.0@html||.info@html||.jianjie@html}}</p >
<!-- 显示总页数 -->
<p id="page">共<span id="total-pages">0</span>页</p >
<!-- 显示拼接的URL列表 -->
<div id="urls"></div>
<!-- 加载进度信息 -->
<div id="loading">加载中 0%</div>
<!-- 视频地址 -->
<div id="video-url"></div>
<!-- 视频容器 -->
<div id="video-container"><video id="video-player" controls></video></div>
<div id="video-sources"></div>
<div id="controls">
</div>
<!-- 图片容器 -->
<div id="images"></div>
<!-- 文本容器 -->
<div id="text"></div>
<script>
$(document).ready(function () {
    // 初始化变量
    let isPlaying = false;
    let videoDuration = 0;
    let currentTime = 0;
    const videoElement = $('#video-player').get(0);
    let hls = null;

    // 函数用于向URL添加后缀,如果URL已包含该后缀则不添加
    function addSuffix(url, suffix) {
      if (!suffix) {
            return url;
      }
      if (url.endsWith(suffix)) {
            return url;
      }
      return `${url}${suffix}`;
    }

    // 根据视频文件的扩展名返回相应的MIME类型
    function getVideoType(src) {
      const extension = src.split('.').pop().toLowerCase();
      switch (extension) {
            case 'm3u8':
                return 'application/x-mpegURL';
            case 'mp4':
                return 'video/mp4';
            case 'webm':
                return 'video/webm';
            case 'ogg':
                return 'video/ogg';
            case 'flv':
                return 'video/x-flv';
            default:
                console.warn(`未知的视频格式: ${extension}`);
                return 'video/*'; // 使用通配符作为默认值
      }
    }

    // 更新进度条函数
    function updateProgressBar() {
      if (videoDuration > 0) {
            const progressPercent = (currentTime / videoDuration) * 100;
            $('#video-progress-filled').css('width', `${progressPercent}%`);
      }
    }

    // 绑定视频播放事件
    videoElement.addEventListener('loadedmetadata', function () {
      videoDuration = this.duration;
      updateProgressBar();
    });

    videoElement.addEventListener('timeupdate', function () {
      currentTime = this.currentTime;
      updateProgressBar();
    });

    videoElement.addEventListener('ended', function () {
      isPlaying = false;
    });

    // 初始化图片查看器
    const box = document.getElementById('images');
    if (box) {
      new Viewer(box, { title: true, interval: 3000 });
    }

    // 加载内容的函数
    function loadContent(data) {
      let suffix = ""; // 自定义后缀,默认为空,不添加。
      let videoSources = [];

      // (视频修改处1)开始视频提取
      const playsourceLinks = $(data).find('main');
      playsourceLinks.each(function () {
            const src = $(this).find('video').attr('src') || $(this).find('video').attr('href');
            if (src && !videoSources.includes(src)) {
                videoSources.push(addSuffix(src, suffix));
            }
      });

      // (视频修改处2)正则表达式匹配正常视频地址
      if (videoSources.length === 0) {
            const regex = /https?:\/\/[\w.-]+(?:\/[^\s?#]*)?(?:\.(m3u8|mp4|webm|ogg|flv))(?:[^\s'"]*)/ig;
            const matches = data.match(regex);
            if (matches) {
                videoSources = [...new Set(matches)].map(url => addSuffix(url, suffix));
            }
      }

      // (视频修改处3)正则表达式匹配非正常视频地址(假设存在这样的需求)
      if (videoSources.length === 0) {
            try {
                const domainMatch = data.match(/var domain = "([^"]+)";/);
                const scriptContentMatches = [...data.matchAll(/var videos = ([^;]+);/g)];

                if (!domainMatch || scriptContentMatches.length === 0) {
                  throw new Error('未能正确匹配到 domain 或 videos');
                }

                const domain = domainMatch.replace(/\/+$/, '');
                let allVideos = [];

                for (const match of scriptContentMatches) {
                  try {
                        const parsedVideos = JSON.parse(match.replace(/\\(?=[\\/])|\\[^u]/g, ''));
                        allVideos = allVideos.concat(parsedVideos);
                  } catch (jsonError) {
                        console.error('无法解析部分 videos JSON 数据', jsonError);
                  }
                }

                videoSources = allVideos.map(video => {
                  const urlPath = video.url.replace(/^\/+|\/+$/g, '');
                  const fullUrl = `${domain}/${urlPath}`;
                  return fullUrl;
                }).filter((value, index, self) => self.indexOf(value) === index);

            } catch (error) {
                console.error(error.message);
            }
      }

      // (视频修改处4)处理视频,域名替换并添加后缀(默认suffix为空)
      const targetDomains = [
            // 填写自定义域名,每个域名以斜杠结尾
      ].map(domain => domain.endsWith('/') ? domain : domain + '/');

      if (targetDomains.length > 0) {
            videoSources = [...new Set(videoSources.flatMap(originalSrc => {
                let sources = ;

                targetDomains.forEach(domain => {
                  const pathStartIndex = originalSrc.indexOf('/', 8); // 跳过协议部分(http:// 或 https://)
                  const path = pathStartIndex !== -1 ? originalSrc.substring(pathStartIndex) : '';
                  const replacedSrc = domain + path;

                  if (!videoSources.includes(replacedSrc)) {
                        sources.push(addSuffix(replacedSrc, suffix));
                  }
                });

                return sources;
            }))]; // 去重
      }

      // 如果有视频源,则初始化视频源选择器和视频播放界面
      if (videoSources.length > 0) {
            // 初始化视频源选择器
            const videoSourceSelect = $('<select id="video-source-select"></select>');
            videoSources.forEach((src, idx) => {
                const option = $(`<option value="${src}" style="height: 20px; width: 100%;">${idx + 1} 号源</option>`);
                if (idx === 0) {
                  option.attr('selected', 'selected');
                }
                videoSourceSelect.append(option);
            });

            videoSourceSelect.change(function () {
                const selectedSrc = $(this).val();
                videoElement.src = selectedSrc;
                $('#video-url').html(`<p>视频地址: ${selectedSrc}</p >`);

                if (!videoElement.canPlayType('application/vnd.apple.mpegurl') && Hls.isSupported()) {
                  if (hls) {
                        hls.destroy();
                  }
                  hls = new Hls();
                  hls.loadSource(selectedSrc);
                  hls.attachMedia(videoElement);
                  hls.on(Hls.Events.MANIFEST_PARSED, () => {
                        videoElement.play();
                  });
                } else {
                  videoElement.load();
                }
                updateProgressBar();
            });

            videoSourceSelect.appendTo('#video-sources');

            // 设置第一个视频为当前源,并显示视频地址
            videoElement.src = videoSources;
            // 更新 #video-url 显示第一个视频源地址
            $('#video-url').html(`<p>视频地址: ${videoSources}</p >`);

            // 如果使用HLS流媒体格式并且浏览器不支持原生播放,则初始化Hls.js
            if (!videoElement.canPlayType('application/vnd.apple.mpegurl') && Hls.isSupported()) {
                hls = new Hls();
                hls.loadSource(videoSources);
                hls.attachMedia(videoElement);
                hls.on(Hls.Events.MANIFEST_PARSED, () => {
                  videoElement.play();
                });
            } else {
                videoElement.load();
            }
      } else {
            // 如果没有找到视频源,隐藏视频容器
            $('#video-container').hide();
            $('#video-sources').hide();
            $('#video-url').hide();
      }

      // 调用一次updateProgressBar确保进度条同步
      updateProgressBar();

      // (图片修改处)提取图片
      $(data).find('figure img').each(function () {
            $('#images').append($(this).clone());
            if (box) {
                box.viewer.update();
            }
      });

      // (文本修改处)提取文本
      $(data).find('.col-12 p').each(function () {
            const content = $(this).text().trim().replace(/<br\s*\/?>/gi, '\n');
            if (content) {
                $('#text').append(`<p>${content}</p ><br>`);
            }
      });

      $('#loading').hide();
    }

    // (修改处)获取页面总数和基础URL
    const totalPagesText = '{{@@.pager.0@a.-2@textNodes##\n.*}}'; // 替换为实际获取方式
    const totalPages = parseInt(totalPagesText) || 1;
    $('#total-pages').text(totalPages);

    const baseUrl = '{{baseUrl}}'; // 替换为实际获取方式
    const urlPrefix = baseUrl.replace('.html', '/');
    var urls = [];
    if (totalPages === 1) {
      urls.push(baseUrl);
    } else {
      urls.push(baseUrl);
      for (let i = 2; i <= totalPages; i++) {
            urls.push(urlPrefix + i + '.html'); // 网址拼接修改处。
      }
    }

    $('#urls').html('<p>拼接的网址:</p >').append(
      urls.map((url, index) => `<p>${index + 1}: ${url}</p >`).join('')
    );

    // 加载内容
    function loadPageContent(url, callback) {
      $.ajax({
            url: url,
            success: function (data) {
                loadContent(data);
                callback(null, data);
            },
            error: function (xhr, status, error) {
                console.error(`内容加载失败: ${url}`, xhr, status, error);
                callback(error);
            }
      });
    }

    function loadPagesSequentially(urls, index = 0, callback) {
      if (index >= urls.length) {
            return callback();
      }

      loadPageContent(urls, (err, data) => {
            if (err) {
                return callback(err);
            }
            loadPagesSequentially(urls, index + 1, callback);
      });
    }

    loadPagesSequentially(urls, 0, (err) => {
      if (err) {
            console.error('所有页面加载完成时发生错误:', err);
      } else {
            console.log('所有页面加载完成');
      }
    });
});
</script>
</body>
</html>

良有益 发表于 2024-12-3 17:28:01

本帖最后由 良有益 于 2024-12-4 11:13 编辑

已重新修改,无视频地址,不显示播放界面,有些图片获取到了,但不显示,可以尝试加入{{@@script@html}}

焸焸 发表于 2024-12-3 17:32:29

好强啊

Sylt1122 发表于 2024-12-3 17:35:06

感谢分享

鹅不食草 发表于 2024-12-3 17:36:49

感谢分享

肉松小贝 发表于 2024-12-3 17:45:20

感谢分享

爱吃猫的鱼 发表于 2024-12-3 18:07:20

感谢分享

Hjigjj 发表于 2024-12-3 19:10:12

感谢分享

Sothis 发表于 2024-12-3 19:38:54

不懂好厉害

注册 发表于 2024-12-3 20:00:57

感谢分享
页: [1] 2 3 4 5 6 7
查看完整版本: 多功能阅读rss模板