IPTV linker Extractor

提取并复制IPTV内容

当前为 2024-09-06 提交的版本,查看 最新版本

// ==UserScript==
// @name         IPTV linker Extractor
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  提取并复制IPTV内容
// @author       zephyr
// @match        http://www.foodieguide.com/iptvsearch*
// @match        http://foodieguide.com/iptvsearch*
// @match        http://tonkiang.us/*
// @match        https://www.foodieguide.com/iptvsearch*
// @match        https://foodieguide.com/iptvsearch*
// @grant        GM_setClipboard
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // 添加样式
    GM_addStyle(`
        #copyButton {
            position: fixed;
            top: 40px;
            right: 20px;
            padding: 10px 15px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            z-index: 1000;
        }
        #copyButton:hover {
            background-color: #45a049;
        }
    `);

    // 创建并插入按钮
    const button = document.createElement('button');
    button.id = 'copyButton';
    button.innerText = '一键复制提取内容';
    document.body.appendChild(button);

    // 按钮点击事件
    button.addEventListener('click', function() {
        // 获取所有的结果块,包括 .result, .resultplus 和其他新的结构
        const results = document.querySelectorAll('.result, .resultplus');

        // 创建一个Set来保存提取的数据
        let extractedData = new Set();

        // 遍历每个结果块
        results.forEach(result => {
            let channelName = null;
            let url = null;

            // 处理第一种结构 .result
            const channelNameDiv1 = result.querySelector('.channel a div');
            const urlTd1 = result.querySelector('.m3u8 td:last-child');
            if (channelNameDiv1 && urlTd1) {
                channelName = channelNameDiv1.textContent.trim();
                url = urlTd1.textContent.trim();
            }

            // 处理第二种结构 .liujbm
            const channelNameDiv2 = result.querySelector('.channel > a > div');
            const urlTba2 = result.querySelector('.liujbm tba:nth-child(2)');
            if (channelNameDiv2 && urlTba2) {
                channelName = channelNameDiv2.textContent.trim();
                url = urlTba2.textContent.trim();
            }

            // 处理第三种结构 .ewqjsd
            const channelNameDiv3 = result.querySelector('.channel > a > div');
            const urlTba3 = result.querySelector('.ewqjsd tba:nth-child(2)');
            if (channelNameDiv3 && urlTba3) {
                channelName = channelNameDiv3.textContent.trim();
                url = urlTba3.textContent.trim();
            }

            // 处理第四种结构,提取 .tip 元素的文本值,并通过相对位置查找 URL
            const channelNameDiv4 = result.querySelector('.channel .tip');
            const secondChild = result.children[1]; 
            const gurlTd4 = secondChild ? secondChild.querySelectorAll('tba')[1] : null;
            if (channelNameDiv4 && gurlTd4) {
                channelName = channelNameDiv4.textContent.trim();
                url = gurlTd4.textContent.trim();
            }

            // 处理 .tables .result 结构
            const channelNameElem = result.querySelector('.channel a b');
            if (channelNameElem) {
                const iElements = document.querySelectorAll('.result .channel a');
                // 提取文本值
                channelName = Array.from(iElements).map(i => i.textContent.trim()).join(', ');
                url = channelNameElem.textContent.trim().replace(/<img[^>]*>/g, '').trim();
            }

            // 如果频道名称和URL都存在,则按指定格式添加到Set中
            if (channelName && url) {
                extractedData.add(`${channelName},${url}`);
            }
        });

        // 将Set中的数据拼接成最终的字符串,每行一个频道
        const finalData = Array.from(extractedData).join('\n\n');

        // 复制到剪贴板
        GM_setClipboard(finalData);

        // 通知用户
        alert('提取内容已复制到剪贴板!');
    });

})();