阿里巴巴店铺分组产品数量统计

统计阿里巴巴店铺每个分组的产品数量-从module-data中查找"产品分组"模块

// ==UserScript==
// @name         阿里巴巴店铺分组产品数量统计
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  统计阿里巴巴店铺每个分组的产品数量-从module-data中查找"产品分组"模块
// @author       树洞先生
// @license       MIT
// @match        https://*.alibaba.com/product*
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    // 添加样式
    GM_addStyle(`
        .group-counter-btn {
            position: static;
            top: auto;
            right: auto;
            z-index: auto;
            background: #ff6b35;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 3px;
            cursor: pointer;
            font-size: 12px;
            box-shadow: none;
            margin: 0;
            display: inline-block;
            vertical-align: middle;
        }
        .group-counter-btn:hover {
            background: #e55a2b;
            transform: scale(1.05);
            transition: all 0.2s ease;
        }
        .group-counter-modal {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 10000;
            background: white;
            border-radius: 10px;
            box-shadow: 0 5px 30px rgba(0,0,0,0.3);
            max-width: 600px;
            max-height: 80vh;
            overflow: hidden;
            display: none;
        }
        .group-counter-header {
            background: #ff6b35;
            color: white;
            padding: 15px 20px;
            font-size: 16px;
            font-weight: bold;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .group-counter-header > div {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .group-counter-close {
            background: none;
            border: none;
            color: white;
            font-size: 20px;
            cursor: pointer;
            padding: 0;
            width: 30px;
            height: 30px;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .group-counter-content {
            padding: 20px;
            max-height: 60vh;
            overflow-y: auto;
        }
        .group-item {
            padding: 10px;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .group-item:last-child {
            border-bottom: none;
        }
        .group-item.sub-group {
            margin-left: 20px;
            border-left: 3px solid #ff6b35;
            padding-left: 15px;
            background-color: #f9f9f9;
        }
        .group-name {
            flex: 1;
            font-size: 14px;
        }
        .group-count {
            background: #4CAF50;
            color: white;
            padding: 4px 8px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: bold;
            min-width: 40px;
            text-align: center;
        }
        .group-count.loading {
            background: #FF9800;
        }
        .group-count.error {
            background: #F44336;
        }
        .loading-spinner {
            display: inline-block;
            width: 12px;
            height: 12px;
            border: 2px solid #ffffff;
            border-radius: 50%;
            border-top-color: transparent;
            animation: spin 1s ease-in-out infinite;
        }
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        .overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.5);
            z-index: 9999;
            display: none;
        }
        .debug-info {
            background: #f5f5f5;
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 10px;
            margin: 10px 0;
            font-family: monospace;
            font-size: 12px;
            max-height: 200px;
            overflow-y: auto;
        }
        .retry-btn {
            background: #2196F3;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            margin: 10px 5px;
        }
        .retry-btn:hover {
            background: #1976D2;
        }
        .debug-btn {
            background: #2196F3;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            margin: 0 5px;
            font-size: 12px;
        }
        .debug-btn:hover {
            background: #1976D2;
        }
    `);

    // 创建按钮
    function createButton() {
        // 这个函数现在由createButtonWithRetry替代,保留以兼容性
        createButtonWithRetry();
    }

    // 创建模态框
    function createModal() {
        const modal = document.createElement('div');
        modal.className = 'group-counter-modal';
        modal.innerHTML = `
            <div class="group-counter-header">
                <span>店铺分组产品统计</span>
                <div>
                    <button class="retry-btn" id="export-csv-btn">导出CSV</button>
                    <button class="group-counter-close">&times;</button>
                </div>
            </div>
            <div class="group-counter-content">
                <div id="group-list">
                    <div style="text-align: center; padding: 20px;">
                        <div class="loading-spinner"></div>
                        <p>正在分析店铺分组...</p>
                    </div>
                </div>
            </div>
        `;

        // 关闭按钮事件
        modal.querySelector('.group-counter-close').onclick = hideGroupCounter;
        // 导出按钮事件
        const exportBtn = modal.querySelector('#export-csv-btn');
        if (exportBtn) exportBtn.onclick = exportCurrentCountsToCSV;
        
        // 点击遮罩关闭
        modal.onclick = function(e) {
            if (e.target === modal) {
                hideGroupCounter();
            }
        };

        document.body.appendChild(modal);
        return modal;
    }

    // 创建遮罩
    function createOverlay() {
        const overlay = document.createElement('div');
        overlay.className = 'overlay';
        overlay.onclick = hideGroupCounter;
        document.body.appendChild(overlay);
        return overlay;
    }

    // 显示模态框
    function showGroupCounter() {
        const modal = document.querySelector('.group-counter-modal') || createModal();
        const overlay = document.querySelector('.overlay') || createOverlay();
        
        modal.style.display = 'block';
        overlay.style.display = 'block';
        
        // 开始分析分组
        analyzeGroups();
    }

    // 隐藏模态框
    function hideGroupCounter() {
        const modal = document.querySelector('.group-counter-modal');
        const overlay = document.querySelector('.overlay');
        
        if (modal) modal.style.display = 'none';
        if (overlay) overlay.style.display = 'none';
    }

    // 递归生成分组序号和路径 - 参考Python代码的enumerate_groups函数
    function enumerateGroups(groups, parentNames = [], prefix = '') {
        const result = [];
        for (let idx = 0; idx < groups.length; idx++) {
            const group = groups[idx];
            const currentNames = [...parentNames, group.name || group.title || group.text];
            const number = prefix ? `${prefix}.${idx + 1}` : String(idx + 1);
            
            result.push({
                number: number,
                groupPath: currentNames,
                groupObj: group
            });
            
            if (group.children && group.children.length > 0) {
                result.push(...enumerateGroups(group.children, currentNames, number));
            }
        }
        return result;
    }

    // 递归查找moduleTitle - 参考Python代码的find_module_title函数
    function findModuleTitle(obj) {
        if (typeof obj === 'object' && obj !== null) {
            if (obj.moduleTitle) {
                return obj.moduleTitle;
            }
            
            for (const key in obj) {
                const found = findModuleTitle(obj[key]);
                if (found) return found;
            }
        } else if (Array.isArray(obj)) {
            for (const item of obj) {
                const found = findModuleTitle(item);
                if (found) return found;
            }
        }
        return null;
    }


    


    // 从页面中提取产品分类 - 完全按照Python代码的逻辑
    function extractCategoriesFromDOM() {
        console.log('开始从页面中提取产品分类...');
        
        // 首先尝试从当前页面的module-data中查找分组信息(按照Python代码的逻辑)
        console.log('尝试从当前页面的module-data中查找分组信息...');
        
        // 查找module-data
        const moduleDataMatches = document.documentElement.innerHTML.match(/module-data=(["\'])(.*?)\1/g);
        if (moduleDataMatches && moduleDataMatches.length > 0) {
            console.log(`当前页面找到 ${moduleDataMatches.length} 个module-data`);
            
            // 按照Python代码的逻辑,寻找"产品分组"模块
            const keepTitle = "产品分组";
            const targetPcTitle = "PC产品列表";
            
            for (let i = 0; i < moduleDataMatches.length; i++) {
                try {
                    const match = moduleDataMatches[i];
                    const moduleDataStr = match.match(/module-data=(["\'])(.*?)\1/)[2];
                    const decoded = decodeURIComponent(moduleDataStr);
                    const dataJson = JSON.parse(decoded);
                    const moduleTitle = findModuleTitle(dataJson);
                    
                    console.log(`模块 ${i + 1} 标题: ${moduleTitle}`);
                    
                    if (moduleTitle === keepTitle) {
                        console.log(`找到匹配的分组模块: ${keepTitle}`);
                        console.log(`完整模块数据结构:`, dataJson);
                        
                        // 按照Python代码的路径:dataJson['mds']['moduleData']['data']['groups']
                        if (dataJson.mds && dataJson.mds.moduleData && dataJson.mds.moduleData.data && dataJson.mds.moduleData.data.groups) {
                            const groups = dataJson.mds.moduleData.data.groups;
                            console.log('从Python代码路径找到分组数据:', groups);
                            
                            // 转换为JavaScript格式,保持层级结构
                            const categories = convertGroupsToCategories(groups);
                            console.log(`成功从module-data中提取到 ${categories.length} 个产品分类(包含子分类)`);
                            return categories;
                        }
                    }
                } catch (e) {
                    console.error(`解析模块 ${i + 1} 失败:`, e);
                    continue;
                }
            }
        }
        
        // 如果module-data中没有找到,尝试从DOM结构中查找
        console.log('module-data中未找到分组信息,尝试从DOM结构中查找...');
        const categories = extractCategoriesFromDOMStructure();
        
        if (categories.length > 0) {
            console.log(`成功从DOM中提取到 ${categories.length} 个产品分类(包含子分类)`);
            return categories;
        }
        
        console.log('从页面中未找到产品分类');
        return [];
    }
    
    // 从DOM结构中提取产品分类,支持二级分组
    function extractCategoriesFromDOMStructure() {
        const categories = [];
        
        // 尝试多种可能的选择器来找到产品分类容器
        const containerSelectors = [
            // 左侧产品分类容器
            '.category-list',
            '.product-category', 
            '.category-item',
            '.sidebar .category',
            '.left-sidebar .category',
            // 更通用的选择器
            '[class*="category"]',
            '[class*="分类"]',
            '.sidebar',
            '.left-sidebar'
        ];
        
        let categoryContainer = null;
        for (const selector of containerSelectors) {
            const container = document.querySelector(selector);
            if (container) {
                console.log(`找到分类容器: ${selector}`);
                categoryContainer = container;
                break;
            }
        }
        
        if (!categoryContainer) {
            // 如果没找到明确的容器,尝试查找包含"产品分类"文字的容器
            const allElements = document.querySelectorAll('*');
            for (const element of allElements) {
                if (element.textContent && element.textContent.includes('产品分类')) {
                    console.log('找到包含"产品分类"的容器:', element);
                    categoryContainer = element;
                    break;
                }
            }
        }
        
        if (categoryContainer) {
            // 递归提取分类,支持二级分组
            const extractedCategories = extractCategoriesRecursively(categoryContainer);
            categories.push(...extractedCategories);
        }
        
        return categories;
    }
    
    // 递归提取分类,支持多级分组
    function extractCategoriesRecursively(container, level = 0) {
        const categories = [];
        
        // 查找当前级别的分类链接
        const links = container.querySelectorAll(':scope > a, :scope > li > a, :scope > div > a');
        
        for (const link of links) {
            const text = link.textContent.trim();
            const href = link.getAttribute('href');
            
            if (text && text.length > 0 && text.length < 100) {
                // 过滤掉一些明显不是分类的文本
                if (!text.match(/^(首页|首页|联系我们|关于我们|公司简介|新闻|博客|帮助|搜索|登录|注册|English|中文)$/i)) {
                    const category = {
                        name: text,
                        url: href || '',
                        text: text,
                        level: level,
                        children: []
                    };
                    
                    // 查找子分类 - 改进的算法
                    const parentElement = link.parentElement;
                    if (parentElement) {
                        // 方法1: 查找同级的下一个元素,看是否包含子分类
                        let nextSibling = parentElement.nextElementSibling;
                        while (nextSibling && nextSibling.tagName === 'LI') {
                            // 检查这个元素是否包含子分类链接
                            const childLinks = nextSibling.querySelectorAll('a');
                            if (childLinks.length > 0) {
                                for (const childLink of childLinks) {
                                    const childText = childLink.textContent.trim();
                                    const childHref = childLink.getAttribute('href');
                                    
                                    if (childText && childText.length > 0 && childText.length < 100) {
                                        if (!childText.match(/^(首页|首页|联系我们|关于我们|公司简介|新闻|博客|帮助|搜索|登录|注册|English|中文)$/i)) {
                                            category.children.push({
                                                name: childText,
                                                url: childHref || '',
                                                text: childText,
                                                level: level + 1
                                            });
                                        }
                                    }
                                }
                                break;
                            }
                            nextSibling = nextSibling.nextElementSibling;
                        }
                        
                        // 方法2: 查找父元素的子元素,可能包含子分类
                        if (category.children.length === 0) {
                            const parentParent = parentElement.parentElement;
                            if (parentParent) {
                                // 查找包含当前链接的容器内的其他链接
                                const allLinksInContainer = parentParent.querySelectorAll('a');
                                for (const otherLink of allLinksInContainer) {
                                    if (otherLink !== link && otherLink.textContent.trim() !== text) {
                                        const otherText = otherLink.textContent.trim();
                                        const otherHref = otherLink.getAttribute('href');
                                        
                                        // 检查是否是子分类(通常子分类的文本更短,URL更具体)
                                        if (otherText && otherText.length > 0 && otherText.length < 50 && 
                                            otherHref && otherHref !== href && 
                                            !otherText.match(/^(首页|首页|联系我们|关于我们|公司简介|新闻|博客|帮助|搜索|登录|注册|English|中文)$/i)) {
                                            
                                            // 检查这个链接是否在当前链接之后(DOM顺序)
                                            if (otherLink.compareDocumentPosition(link) & Node.DOCUMENT_POSITION_FOLLOWING) {
                                                category.children.push({
                                                    name: otherText,
                                                    url: otherHref,
                                                    text: otherText,
                                                    level: level + 1
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        
                        // 方法3: 查找特定的阿里巴巴分类结构
                        if (category.children.length === 0) {
                            // 查找包含"产品分类"文字的容器内的所有链接
                            const categorySection = container.closest('[class*="category"], [class*="分类"], .sidebar, .left-sidebar');
                            if (categorySection) {
                                const allCategoryLinks = categorySection.querySelectorAll('a');
                                let foundMainCategory = false;
                                
                                for (const catLink of allCategoryLinks) {
                                    const catText = catLink.textContent.trim();
                                    const catHref = catLink.getAttribute('href');
                                    
                                    if (catLink === link) {
                                        foundMainCategory = true;
                                        continue;
                                    }
                                    
                                    if (foundMainCategory && catText && catText.length > 0 && catText.length < 50 && 
                                        catHref && catHref !== href && 
                                        !catText.match(/^(首页|首页|联系我们|关于我们|公司简介|新闻|博客|帮助|搜索|登录|注册|English|中文)$/i)) {
                                        
                                        // 检查是否是子分类(通过URL模式判断)
                                        if (catHref.includes('product') || catHref.includes('category') || catHref.includes('group')) {
                                            category.children.push({
                                                name: catText,
                                                url: catHref,
                                                text: catText,
                                                level: level + 1
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                    
                    categories.push(category);
                    console.log(`找到${level === 0 ? '一级' : '二级'}分类: ${text}, URL: ${href}, 子分类数量: ${category.children.length}`);
                }
            }
        }
        
        return categories;
    }
    
    // 将module-data中的分组数据转换为分类格式,保持层级结构
    function convertGroupsToCategories(groups) {
        const categories = [];
        
        for (const group of groups) {
            const category = {
                name: group.name || group.title || group.text || '未知分组',
                url: group.url || '',
                text: group.name || group.title || group.text || '未知分组',
                level: 0,
                children: []
            };
            
            // 处理子分组
            if (group.children && group.children.length > 0) {
                for (const child of group.children) {
                    category.children.push({
                        name: child.name || child.title || child.text || '未知子分组',
                        url: child.url || '',
                        text: child.name || child.title || child.text || '未知子分组',
                        level: 1
                    });
                }
            }
            
            categories.push(category);
        }
        
        return categories;
    }
     
     // 显示从DOM中提取的分组数据
     function displayGroupsFromDOM(groups, baseUrl) {
         console.log('显示从DOM中提取的分组数据:', groups);
         
         const groupList = document.getElementById('group-list');
         
         // 显示分组列表
         let htmlContent = '';
         
         // 添加全店产品
         htmlContent += `
             <div class="group-item">
                 <span class="group-name">0. 全店所有产品</span>
                 <span class="group-count loading" id="count-all-store">
                     <span class="loading-spinner"></span>
                 </span>
             </div>
         `;
         
         // 添加橱窗产品
         htmlContent += `
             <div class="group-item">
                 <span class="group-name">0.1. 橱窗产品</span>
                 <span class="group-count loading" id="count-featured">
                     <span class="loading-spinner"></span>
                 </span>
             </div>
         `;
         
         // 添加从DOM中提取的分组,包括二级分组
         let groupIndex = 1;
         for (let i = 0; i < groups.length; i++) {
             const group = groups[i];
             
             // 显示一级分组
             htmlContent += `
                 <div class="group-item">
                     <span class="group-name">${groupIndex}. ${group.name}</span>
                     <span class="group-count loading" id="count-dom-${i}-main">
                         <span class="loading-spinner"></span>
                     </span>
                 </div>
             `;
             
             // 显示二级分组(子分类)
             if (group.children && group.children.length > 0) {
                 for (let j = 0; j < group.children.length; j++) {
                     const child = group.children[j];
                     htmlContent += `
                         <div class="group-item sub-group" style="margin-left: 20px;">
                             <span class="group-name">${groupIndex}.${j + 1}. ${child.name}</span>
                             <span class="group-count loading" id="count-dom-${i}-child-${j}">
                                 <span class="loading-spinner"></span>
                             </span>
                         </div>
                     `;
                 }
             }
             
             groupIndex++;
         }
         
         groupList.innerHTML = htmlContent;
         
         // 异步获取产品数量
         getProductCountsFromDOM(baseUrl, groups);
     }
     
     // 并发执行器(限制最大并发数)
     async function runTasksWithConcurrency(tasks, worker, limit = 8) {
         const results = new Array(tasks.length);
         let nextIndex = 0;
         let active = 0;
         return new Promise((resolve) => {
             const runNext = () => {
                 while (active < limit && nextIndex < tasks.length) {
                     const current = nextIndex++;
                     active++;
                     Promise.resolve(worker(tasks[current], current))
                         .then((res) => { results[current] = res; })
                         .catch((err) => { results[current] = err; })
                         .finally(() => {
                             active--;
                             if (nextIndex === tasks.length && active === 0) {
                                 resolve(results);
                             } else {
                                 runNext();
                             }
                         });
                 }
             };
             runNext();
         });
     }

     function sanitizeListingUrl(u) {
         if (!u) return u;
         try {
             // 移除跟踪参数(如 ?spm=...)及所有查询串/哈希,保证列表页可返回正确模块
             const cleaned = u.replace(/[?#].*$/, '');
             console.log(`URL清理: "${u}" -> "${cleaned}"`);
             return cleaned;
         } catch (e) {
             console.error('URL清理失败:', e);
             return u;
         }
     }

     function resolveUrl(rawUrl, baseUrl) {
         if (!rawUrl) return null;
         let full;
         if (rawUrl.startsWith('http')) full = rawUrl;
         else if (rawUrl.startsWith('/')) full = baseUrl + rawUrl;
         else full = baseUrl + '/' + rawUrl;
         return sanitizeListingUrl(full);
     }

     // 获取从DOM中提取的分组的产品数量
     async function getProductCountsFromDOM(baseUrl, groups) {
         try {
             const tasks = [];
             let seq = 0;
             // 全店与橱窗
             tasks.push({ id: 'count-all-store', url: sanitizeListingUrl(baseUrl + '/productlist.html'), label: '全店所有产品', parent: '', seq: seq++ });
             tasks.push({ id: 'count-featured', url: sanitizeListingUrl(baseUrl + '/featureproductlist-1.html'), label: '橱窗产品', parent: '', seq: seq++ });

             // 各分组与子分组
             for (let i = 0; i < groups.length; i++) {
                 const group = groups[i];
                 const mainUrl = resolveUrl(group.url, baseUrl);
                 if (mainUrl) {
                     tasks.push({ id: `count-dom-${i}-main`, url: mainUrl, label: group.name || `分组${i+1}`, parent: '', seq: seq++ });
                 } else {
                     updateCountDisplay(`count-dom-${i}-main`, 0);
                 }
                 if (group.children && group.children.length > 0) {
                     for (let j = 0; j < group.children.length; j++) {
                         const child = group.children[j];
                         const childUrl = resolveUrl(child.url, baseUrl);
                         if (childUrl) {
                             tasks.push({ id: `count-dom-${i}-child-${j}`, url: childUrl, label: child.name || `子分组${j+1}`, parent: group.name || `分组${i+1}`, seq: seq++ });
                         } else {
                             updateCountDisplay(`count-dom-${i}-child-${j}`, 0);
                         }
                     }
                 }
             }

            await runTasksWithConcurrency(tasks, async (task) => {
                const cnt = await getImprovedProductCount(sanitizeListingUrl(task.url), "PC产品列表");
                updateCountDisplay(task.id, cnt);
                collectCountForExport(task, cnt);
            }, 8);
         } catch (e) {
             console.error('获取产品数量失败:', e);
         }
     }
     
     // 分析店铺分组 - 参考Python代码的主要逻辑
     async function analyzeGroups() {
        const groupList = document.getElementById('group-list');
        const currentUrl = window.location.href;
        
        try {
            // 获取店铺基础URL - 参考Python代码的URL处理逻辑,并清理所有查询参数
            let baseUrl = sanitizeListingUrl(currentUrl);
            if (baseUrl.includes('/productlist.html')) {
                baseUrl = baseUrl.replace('/productlist.html', '');
            } else if (baseUrl.includes('/featureproductlist-')) {
                baseUrl = baseUrl.replace(/\/featureproductlist-\d+\.html/, '');
            } else if (baseUrl.includes('/productgrouplist-')) {
                baseUrl = baseUrl.replace(/\/productgrouplist-\d+.*/, '');
            }
            
            console.log('清理后的店铺基础URL:', baseUrl);
            
                         groupList.innerHTML = '<p>正在分析页面结构...</p>';
             
             // 首先尝试从当前页面的DOM结构中直接提取产品分类
             console.log('尝试从页面DOM结构中提取产品分类...');
             let groups = extractCategoriesFromDOM();
             
             if (groups.length > 0) {
                 console.log('从DOM结构成功提取到产品分类:', groups);
                 displayGroupsFromDOM(groups, baseUrl);
                 return;
             }
             
             // 如果DOM中没有找到,尝试从module-data中查找
             console.log('DOM中未找到产品分类,尝试从module-data中查找...');
             
             // 获取店铺主页面 - 使用清理后的URL
             const mainPageUrl = sanitizeListingUrl(baseUrl + '/productlist.html');
             console.log('获取店铺主页面URL:', mainPageUrl);
             const response = await fetch(mainPageUrl);
             const html = await response.text();
             
             // 调试信息:检查页面内容
             console.log('页面大小:', html.length);
             console.log('页面URL:', mainPageUrl);
             
             // 查找module-data - 参考Python代码的匹配逻辑
             const moduleDataMatches = html.match(/module-data=(["\'])(.*?)\1/g);
             console.log('找到module-data数量:', moduleDataMatches ? moduleDataMatches.length : 0);
             
             if (!moduleDataMatches || moduleDataMatches.length === 0) {
                 groupList.innerHTML = `
                     <p style="color: orange;">未找到module-data,尝试其他数据源...</p>
                     <p>页面大小: ${html.length} 字符</p>
                     <p>正在检查页面结构...</p>
                 `;
                 
                 await checkAlternativeDataSources(html, groupList, baseUrl);
                 return;
             }
                         // 尝试多个可能的模块标题 - 参考Python代码的逻辑,但增加更多匹配选项
             const possibleKeepTitles = ["产品分组", "分类商品", "商品分类", "产品分类"];
             const targetPcTitle = "PC产品列表";  // 参考Python代码的target_pc_title
             
             // 记录所有找到的模块标题,帮助调试
             const allModuleTitles = [];
            
            // 解析分组数据 - 参考Python代码的解析逻辑
            for (let i = 0; i < moduleDataMatches.length; i++) {
                const match = moduleDataMatches[i];
                try {
                    const moduleDataStr = match.match(/module-data=(["\'])(.*?)\1/)[2];
                    const decoded = decodeURIComponent(moduleDataStr);
                    const dataJson = JSON.parse(decoded);
                    const moduleTitle = findModuleTitle(dataJson);
                    
                                         console.log(`模块 ${i + 1} 标题:`, moduleTitle);
                     console.log(`模块 ${i + 1} 数据结构:`, dataJson);
                     
                     // 记录所有模块标题
                     if (moduleTitle) {
                         allModuleTitles.push(moduleTitle);
                     }
                     
                     // 检查是否匹配任何可能的分组模块标题
                     if (possibleKeepTitles.includes(moduleTitle)) {
                        console.log(`找到匹配的分组模块: ${moduleTitle}`);
                        console.log(`完整模块数据结构:`, dataJson);
                        
                        // 尝试多种可能的数据结构 - 参考Python代码的路径
                        console.log('检查 dataJson.mds:', dataJson.mds);
                        if (dataJson.mds) {
                            console.log('检查 dataJson.mds.moduleData:', dataJson.mds.moduleData);
                            if (dataJson.mds.moduleData) {
                                console.log('检查 dataJson.mds.moduleData.data:', dataJson.mds.moduleData.data);
                                
                                // 如果data字段不存在,尝试从moduleData的其他字段中寻找分组信息
                                if (dataJson.mds.moduleData.data) {
                                    const moduleData = dataJson.mds.moduleData.data;
                                    console.log(`模块数据字段:`, Object.keys(moduleData));
                                    console.log('模块数据内容:', moduleData);
                                    
                                    // 尝试不同的分组数据字段
                                                                         if (moduleData.groups && moduleData.groups.length > 0) {
                                         groups = moduleData.groups;
                                         console.log('从groups字段找到分组数据:', groups);
                                         
                                         // 检查分组数据中是否包含产品数量信息
                                         for (const group of groups) {
                                             console.log('分组详情:', group);
                                             console.log('分组字段:', Object.keys(group));
                                             
                                             // 检查是否有产品数量相关字段
                                             if (group.productCount !== undefined) {
                                                 console.log('分组产品数量字段:', group.productCount);
                                                 console.log('注意:这个数量可能是全店总数,不是分组特定数量');
                                             }
                                             if (group.count !== undefined) {
                                                 console.log('分组数量字段:', group.count);
                                             }
                                             if (group.total !== undefined) {
                                                 console.log('分组总数字段:', group.total);
                                             }
                                             
                                             // 检查是否有其他可能包含分组特定数量的字段
                                             for (const key in group) {
                                                 if (key !== 'productCount' && key !== 'count' && key !== 'total') {
                                                     const value = group[key];
                                                     if (typeof value === 'number' && value > 0 && value < 1000) {
                                                         console.log(`可能的数量字段 ${key}:`, value);
                                                     }
                                                 }
                                             }
                                             
                                             if (group.children && group.children.length > 0) {
                                                 for (const child of group.children) {
                                                     console.log('子分组详情:', child);
                                                     console.log('子分组字段:', Object.keys(child));
                                                     
                                                     if (child.productCount !== undefined) {
                                                         console.log('子分组产品数量字段:', child.productCount);
                                                         console.log('注意:这个数量可能是全店总数,不是子分组特定数量');
                                                     }
                                                     if (child.count !== undefined) {
                                                         console.log('子分组数量字段:', child.count);
                                                     }
                                                     if (child.total !== undefined) {
                                                         console.log('子分组总数字段:', child.total);
                                                     }
                                                     
                                                     // 检查子分组是否有其他可能包含数量的字段
                                                     for (const key in child) {
                                                         if (key !== 'productCount' && key !== 'count' && key !== 'total') {
                                                             const value = child[key];
                                                             if (typeof value === 'number' && value > 0 && value < 1000) {
                                                                 console.log(`子分组可能的数量字段 ${key}:`, value);
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                         break;
                                    } else if (moduleData.categories && moduleData.categories.length > 0) {
                                        groups = moduleData.categories;
                                        console.log('从categories字段找到分组数据:', groups);
                                        break;
                                    } else if (moduleData.productGroups && moduleData.productGroups.length > 0) {
                                        groups = moduleData.productGroups;
                                        console.log('从productGroups字段找到分组数据:', groups);
                                        break;
                                    } else if (moduleData.productCategories && moduleData.productCategories.length > 0) {
                                        groups = moduleData.productCategories;
                                        console.log('从productCategories字段找到分组数据:', groups);
                                        break;
                                    } else {
                                        console.log('模块数据结构:', moduleData);
                                        // 如果没有找到标准字段,尝试遍历所有字段寻找分组数据
                                        for (const key in moduleData) {
                                            if (Array.isArray(moduleData[key]) && moduleData[key].length > 0) {
                                                const firstItem = moduleData[key][0];
                                                console.log(`检查字段 ${key}:`, moduleData[key]);
                                                if (firstItem && (firstItem.name || firstItem.title || firstItem.categoryName)) {
                                                    console.log(`尝试使用字段 ${key} 作为分组数据:`, moduleData[key]);
                                                    groups = moduleData[key];
                                                    break;
                                                }
                                            }
                                        }
                                        if (groups.length > 0) break;
                                    }
                                } else {
                                    console.log('dataJson.mds.moduleData.data 不存在,尝试从moduleData中寻找分组信息');
                                    
                                    // 检查moduleData中是否有其他可能包含分组信息的字段
                                    const moduleData = dataJson.mds.moduleData;
                                    console.log('moduleData字段:', Object.keys(moduleData));
                                    console.log('moduleData内容:', moduleData);
                                    
                                    // 尝试从moduleData中寻找分组数据
                                    for (const key in moduleData) {
                                        if (Array.isArray(moduleData[key]) && moduleData[key].length > 0) {
                                            const firstItem = moduleData[key][0];
                                            console.log(`检查moduleData字段 ${key}:`, moduleData[key]);
                                            if (firstItem && (firstItem.name || firstItem.title || firstItem.categoryName || firstItem.text)) {
                                                console.log(`尝试使用moduleData字段 ${key} 作为分组数据:`, moduleData[key]);
                                                groups = moduleData[key];
                                                break;
                                            }
                                        }
                                    }
                                    if (groups.length > 0) break;
                                }
                            } else {
                                console.log('dataJson.mds.moduleData 不存在');
                            }
                        } else {
                            console.log('dataJson.mds 不存在');
                        }
                        
                        // 尝试其他可能的数据路径
                        if (dataJson.mds && dataJson.mds.data) {
                            console.log('尝试 mds.data 路径:', dataJson.mds.data);
                            const altData = dataJson.mds.data;
                            if (altData.groups && altData.groups.length > 0) {
                                groups = altData.groups;
                                console.log('从 mds.data.groups 找到分组数据:', groups);
                                break;
                            }
                        }
                        if (dataJson.data) {
                            console.log('尝试 data 路径:', dataJson.data);
                            const altData = dataJson.data;
                            if (altData.groups && altData.groups.length > 0) {
                                groups = altData.groups;
                                console.log('从 data.groups 找到分组数据:', groups);
                                break;
                            }
                        }
                        
                        // 尝试直接访问Python代码使用的路径
                        try {
                            if (dataJson.mds && dataJson.mds.moduleData && dataJson.mds.moduleData.data && dataJson.mds.moduleData.data.groups) {
                                groups = dataJson.mds.moduleData.data.groups;
                                console.log('从Python代码路径找到分组数据:', groups);
                                break;
                            }
                        } catch (e) {
                            console.log('Python代码路径访问失败:', e);
                        }
                    }
                } catch (e) {
                    console.error(`解析模块 ${i + 1} 失败:`, e);
                    continue;
                }
            }
            
                         if (groups.length === 0) {
                 console.log('所有找到的模块标题:', allModuleTitles);
                 
                 // 尝试从其他可能包含分组信息的模块中提取数据
                 console.log('尝试从其他模块中寻找分组信息...');
                 for (let i = 0; i < moduleDataMatches.length; i++) {
                     try {
                         const match = moduleDataMatches[i];
                         const moduleDataStr = match.match(/module-data=(["\'])(.*?)\1/)[2];
                         const decoded = decodeURIComponent(moduleDataStr);
                         const dataJson = JSON.parse(decoded);
                         const moduleTitle = findModuleTitle(dataJson);
                         
                         console.log(`检查模块 ${i + 1} (${moduleTitle}) 是否包含分组信息...`);
                         
                         // 尝试从各种可能的数据结构中寻找分组信息
                         if (dataJson.mds && dataJson.mds.moduleData && dataJson.mds.moduleData.data) {
                             const moduleData = dataJson.mds.moduleData.data;
                             console.log(`模块 ${i + 1} 数据结构:`, moduleData);
                             
                             // 检查是否有任何数组字段可能包含分组信息
                             for (const key in moduleData) {
                                 if (Array.isArray(moduleData[key]) && moduleData[key].length > 0) {
                                     const firstItem = moduleData[key][0];
                                     console.log(`检查字段 ${key}:`, moduleData[key]);
                                     if (firstItem && (firstItem.name || firstItem.title || firstItem.categoryName || firstItem.text || firstItem.groupName)) {
                                         console.log(`尝试使用字段 ${key} 作为分组数据:`, moduleData[key]);
                                         groups = moduleData[key];
                                         console.log(`从模块 ${i + 1} (${moduleTitle}) 的字段 ${key} 找到分组数据`);
                                         break;
                                     }
                                 }
                             }
                             if (groups.length > 0) break;
                         }
                         
                         // 尝试其他可能的数据路径
                         if (dataJson.data) {
                             const altData = dataJson.data;
                             for (const key in altData) {
                                 if (Array.isArray(altData[key]) && altData[key].length > 0) {
                                     const firstItem = altData[key][0];
                                     if (firstItem && (firstItem.name || firstItem.title || firstItem.categoryName || firstItem.text || firstItem.groupName)) {
                                         console.log(`从 data.${key} 找到分组数据:`, altData[key]);
                                         groups = altData[key];
                                         break;
                                     }
                                 }
                             }
                             if (groups.length > 0) break;
                         }
                         
                     } catch (e) {
                         console.error(`检查模块 ${i + 1} 失败:`, e);
                         continue;
                     }
                 }
                 
                 if (groups.length === 0) {
                     groupList.innerHTML = `
                         <p style="color: red;">未找到有效的分组数据</p>
                         <p>页面包含以下模块:</p>
                         <ul style="text-align: left; margin: 10px 0;">
                             ${allModuleTitles.map(title => `<li>${title}</li>`).join('')}
                         </ul>
                         <p>已尝试查找以下模块标题:</p>
                         <ul style="text-align: left; margin: 10px 0;">
                             <li>产品分组</li>
                             <li>分类商品</li>
                             <li>商品分类</li>
                             <li>产品分类</li>
                         </ul>
                         <p>可能的原因:</p>
                         <ul style="text-align: left; margin: 10px 0;">
                             <li>页面结构已更新</li>
                             <li>店铺类型不支持分组</li>
                             <li>数据加载不完整</li>
                             <li>分组数据存储在其他字段中</li>
                         </ul>
                         <p>建议:</p>
                         <ul style="text-align: left; margin: 10px 0;">
                             <li>刷新页面后重试</li>
                             <li>检查是否为阿里巴巴店铺页面</li>
                             <li>等待页面完全加载</li>
                             <li>查看控制台日志了解详细数据结构</li>
                         </ul>
                         <button class="retry-btn" onclick="location.reload()">刷新页面</button>
                         <button class="retry-btn" onclick="document.querySelector('.group-counter-modal').style.display='none';document.querySelector('.overlay').style.display='none';setTimeout(()=>{document.querySelector('.group-counter-btn').click()},1000)">重试分析</button>
                     `;
                     return;
                 }
             }
            
            // 递归生成所有分组序号和路径 - 参考Python代码的enumerate_groups调用
            const allEnums = enumerateGroups(groups);
            console.log('生成的分组枚举:', allEnums);
            
            // 显示分组列表
            let htmlContent = '';
            
            // 添加全店产品
            htmlContent += `
                <div class="group-item">
                    <span class="group-name">0. 全店所有产品</span>
                    <span class="group-count loading" id="count-all-store">
                        <span class="loading-spinner"></span>
                    </span>
                </div>
            `;
            
            // 添加橱窗产品
            htmlContent += `
                <div class="group-item">
                    <span class="group-name">0.1. 橱窗产品</span>
                    <span class="group-count loading" id="count-featured">
                        <span class="loading-spinner"></span>
                    </span>
                </div>
            `;
            
            // 添加分组 - 参考Python代码的显示逻辑
            for (const item of allEnums) {
                if (item.groupObj.url) {
                    htmlContent += `
                        <div class="group-item">
                            <span class="group-name">${item.number}. ${item.groupPath.join(' > ')}</span>
                            <span class="group-count loading" id="count-${item.number.replace(/\./g, '-')}">
                                <span class="loading-spinner"></span>
                            </span>
                        </div>
                    `;
                } else {
                    htmlContent += `
                        <div class="group-item">
                            <span class="group-name">${item.number}. ${item.groupPath.join(' > ')}</span>
                            <span class="group-count" style="background: #9E9E9B;">无产品</span>
                        </div>
                    `;
                }
            }
            
            groupList.innerHTML = htmlContent;
            
            // 异步获取产品数量
            await getProductCounts(baseUrl, allEnums, targetPcTitle);
            
        } catch (e) {
            console.error('分析分组失败:', e);
            groupList.innerHTML = `
                <p style="color: red;">分析失败: ${e.message}</p>
                <p>错误详情: ${e.stack}</p>
                <p>请检查控制台获取更多信息</p>
                <button class="retry-btn" onclick="location.reload()">刷新页面</button>
            `;
        }
    }

    // 检查其他数据源
    async function checkAlternativeDataSources(html, groupList, baseUrl) {
        try {
            // 检查是否有其他数据格式
            const possiblePatterns = [
                /window\.__INIT_DATA__\s*=\s*({.*?});/g,
                /window\.__INIT_STATE__\s*=\s*({.*?});/g,
                /window\.productData\s*=\s*({.*?});/g,
                /window\.detailData\s*=\s*({.*?});/g
            ];
            
            let foundData = false;
            for (const pattern of possiblePatterns) {
                const matches = html.match(pattern);
                if (matches && matches.length > 0) {
                    console.log('找到替代数据源:', pattern.source);
                    foundData = true;
                    break;
                }
            }
           
            
            if (!foundData) {
                // 检查页面是否包含产品相关元素
                const hasProducts = html.includes('product') || html.includes('产品') || html.includes('商品');
                const hasGroups = html.includes('group') || html.includes('分组') || html.includes('分类');
                
                groupList.innerHTML = `
                    <p style="color: red;">页面分析结果:</p>
                    <ul style="text-align: left; margin: 10px 0;">
                        <li>包含产品信息: ${hasProducts ? '是' : '否'}</li>
                        <li>包含分组信息: ${hasGroups ? '是' : '否'}</li>
                        <li>页面大小: ${html.length} 字符</li>
                    </ul>
                    <p>建议:</p>
                    <ul style="text-align: left; margin: 10px 0;">
                        <li>确认这是阿里巴巴店铺页面</li>
                        <li>尝试访问店铺主页</li>
                        <li>检查网络连接</li>
                    </ul>
                    <button class="retry-btn" onclick="location.reload()">刷新页面</button>
                    <button class="retry-btn" onclick="document.querySelector('.group-counter-modal').style.display='none';document.querySelector('.overlay').style.display='none';setTimeout(()=>{document.querySelector('.group-counter-btn').click()},1000)">重试分析</button>
                `;
            }
        } catch (e) {
            console.error('检查替代数据源失败:', e);
        }
    }

    // 获取所有分组的产品数量 - 参考Python代码的getProductCounts逻辑
    async function getProductCounts(baseUrl, allEnums, targetPcTitle) {
        try {
            const tasks = [];
            let seq = 0;
            tasks.push({ id: 'count-all-store', url: sanitizeListingUrl(baseUrl + '/productlist.html'), label: '全店所有产品', seq: seq++ });
            tasks.push({ id: 'count-featured', url: sanitizeListingUrl(baseUrl + '/featureproductlist-1.html'), label: '橱窗产品', seq: seq++ });

            for (const item of allEnums) {
                if (item.groupObj.url) {
                    tasks.push({ id: `count-${item.number.replace(/\./g, '-')}`, url: sanitizeListingUrl(baseUrl + item.groupObj.url), label: item.groupPath.join(' > '), seq: seq++ });
                }
            }

            await runTasksWithConcurrency(tasks, async (task) => {
                const cnt = await getImprovedProductCount(sanitizeListingUrl(task.url), targetPcTitle);
                updateCountDisplay(task.id, cnt);
                collectCountForExport(task, cnt);
            }, 8);
        } catch (e) {
            console.error('获取产品数量失败:', e);
        }
    }

    // 更新数量显示
    function updateCountDisplay(countId, count) {
        const countElement = document.getElementById(countId);
        if (!countElement) return;
        
        countElement.className = 'group-count';
        countElement.innerHTML = '';
        
        if (count === -1) {
            countElement.style.background = '#F44336';
            countElement.textContent = '错误';
        } else if (count === 0) {
            countElement.style.background = '#9E9E9B';
            countElement.textContent = '0';
        } else {
            countElement.style.background = '#4CAF50';
            countElement.textContent = count;
        }
    }

    // 导出计数相关
    const exportCounts = [];
    function collectCountForExport(task, count) {
        if (count === -1) return;
        const record = {
            label: task.label || task.id,
            parent: task.parent || '',
            url: sanitizeListingUrl(task.url),
            count: typeof count === 'number' ? count : 0,
            seq: typeof task.seq === 'number' ? task.seq : 999999
        };
        // 若已存在同 id/label 的记录则覆盖
        const idx = exportCounts.findIndex(r => r.label === record.label && r.url === record.url);
        if (idx >= 0) exportCounts[idx] = record; else exportCounts.push(record);
    }

    function exportCurrentCountsToCSV() {
        if (exportCounts.length === 0) {
            alert('暂无可导出的数据,请先统计完成。');
            return;
        }
        const rows = [['分组', '父分组', 'URL', '产品数量']];
        const ordered = [...exportCounts].sort((a,b) => a.seq - b.seq);
        ordered.forEach(item => rows.push([item.label, item.parent, item.url, String(item.count)]));
        const csv = rows.map(r => r.map(v => `"${String(v).replace(/"/g, '""')}"`).join(',')).join('\n');
        const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
        const a = document.createElement('a');
        const host = location.host.replace(/[:\\/]/g, '_');
        a.download = `${host}.csv`;
        a.href = URL.createObjectURL(blob);
        document.body.appendChild(a);
        a.click();
        setTimeout(() => {
            URL.revokeObjectURL(a.href);
            a.remove();
        }, 100);
    }

    // 等待页面加载完成后创建按钮
    function init() {
        console.log('脚本初始化开始,页面状态:', document.readyState);
        
        if (document.readyState === 'loading') {
            console.log('页面正在加载,等待DOMContentLoaded事件');
            document.addEventListener('DOMContentLoaded', () => {
                console.log('DOMContentLoaded事件触发,开始创建按钮');
                setTimeout(createButtonWithRetry, 1000); // 延迟1秒确保页面完全渲染
            });
        } else {
            console.log('页面已加载完成,立即创建按钮');
            setTimeout(createButtonWithRetry, 1000); // 延迟1秒确保页面完全渲染
        }
        
        // 额外监听load事件,确保所有资源加载完成
        window.addEventListener('load', () => {
            console.log('页面所有资源加载完成,检查按钮状态');
            if (!document.querySelector('.group-counter-btn')) {
                console.log('按钮未找到,重新尝试创建');
                setTimeout(createButtonWithRetry, 500);
            }
        });
    }
    
    // 带重试的按钮创建函数
    function createButtonWithRetry() {
        let retryCount = 0;
        const maxRetries = 15;
        
        function tryCreateButton() {
            console.log(`尝试创建按钮,第 ${retryCount + 1} 次...`);
            
            // 方法1: 查找目标容器 - 精确匹配
            const targetDiv = document.querySelector('.title[data-spm-anchor-id="a2700.shop_pl.41413.i16.36887121iAROdA"]');
            if (targetDiv) {
                console.log('找到精确匹配的目标容器:', targetDiv);
                createButtonAtTarget(targetDiv);
                return;
            }
            
            // 方法2: 查找包含特定文本的标题元素
            const titleElements = document.querySelectorAll('[class*="title"], .title, h1, h2, h3, [class*="header"]');
            let found = false;
            
            for (const element of titleElements) {
                const text = element.textContent.trim();
                if (text && (
                    text.includes('All products') || 
                    text.includes('产品分类') ||
                    text.includes('Product categories') ||
                    text.includes('产品列表') ||
                    text.includes('商品分类') ||
                    text.includes('店铺产品') ||
                    text.includes('Store Products')
                )) {
                    console.log('找到包含目标文本的容器:', element, '文本:', text);
                    createButtonAtTarget(element);
                    found = true;
                    break;
                }
            }
            
            if (found) return;
            
            // 方法3: 查找页面中的主要导航或分类区域
            const possibleContainers = [
                '.category-list',
                '.product-category',
                '.sidebar',
                '.left-sidebar',
                '[class*="category"]',
                '[class*="分类"]',
                '.main-content',
                '.content-area'
            ];
            
            for (const selector of possibleContainers) {
                const container = document.querySelector(selector);
                if (container) {
                    console.log(`找到可能的容器: ${selector}`, container);
                    // 在容器内查找合适的标题元素
                    const titleInContainer = container.querySelector('h1, h2, h3, [class*="title"], .title');
                    if (titleInContainer) {
                        console.log('在容器内找到标题元素:', titleInContainer);
                        createButtonAtTarget(titleInContainer);
                        found = true;
                        break;
                    }
                }
            }
            
            if (found) return;
            
            // 方法4: 查找页面中任何包含"产品"或"商品"的元素
            const allElements = document.querySelectorAll('*');
            for (const element of allElements) {
                if (element.children.length === 0 && element.textContent) {
                    const text = element.textContent.trim();
                    if (text && (
                        text.includes('产品分类') ||
                        text.includes('商品分类') ||
                        text.includes('产品列表') ||
                        text.includes('商品列表')
                    )) {
                        const parent = element.parentElement;
                        if (parent && parent.tagName !== 'SCRIPT' && parent.tagName !== 'STYLE') {
                            console.log('找到包含产品相关文本的元素:', element, '文本:', text);
                            createButtonAtTarget(parent);
                            found = true;
                            break;
                        }
                    }
                }
            }
            
            if (found) return;
            
            // 如果还没找到,重试或使用默认位置
            if (retryCount < maxRetries) {
                retryCount++;
                console.log(`未找到目标容器,${retryCount}/${maxRetries} 次重试...`);
                setTimeout(tryCreateButton, 1000); // 1秒后重试
            } else {
                console.log('达到最大重试次数,使用默认位置');
                createButtonAtDefault();
            }
        }
        
        tryCreateButton();
    }
    
    // 在目标位置创建按钮
    function createButtonAtTarget(targetElement) {
        // 检查是否已经存在按钮
        if (targetElement.querySelector('.group-counter-btn')) {
            console.log('按钮已存在,跳过创建');
            return;
        }
        
        try {
            // 创建span标签
            const span = document.createElement('span');
            span.style.cssText = `
                display: inline-block;
                margin-left: 10px;
                vertical-align: middle;
            `;
            
            // 创建按钮
            const btn = document.createElement('button');
            btn.className = 'group-counter-btn';
            btn.textContent = '统计分组产品数';
            btn.onclick = showGroupCounter;
            
            // 调整按钮样式,使其适合内联显示
            btn.style.cssText = `
                position: static;
                top: auto;
                right: auto;
                z-index: auto;
                background: #ff6b35;
                color: white;
                border: none;
                padding: 5px 10px;
                border-radius: 3px;
                cursor: pointer;
                font-size: 12px;
                box-shadow: none;
                margin: 0;
                display: inline-block;
                vertical-align: middle;
            `;
            
            // 将按钮添加到span中
            span.appendChild(btn);
            
            // 尝试将span添加到目标元素
            if (targetElement.appendChild) {
                targetElement.appendChild(span);
                console.log('按钮已成功添加到目标容器右侧:', targetElement);
                return true;
            } else {
                console.log('目标元素不支持appendChild,尝试其他方法');
                // 尝试插入到目标元素之后
                if (targetElement.parentElement && targetElement.parentElement.insertBefore) {
                    targetElement.parentElement.insertBefore(span, targetElement.nextSibling);
                    console.log('按钮已插入到目标元素之后');
                    return true;
                }
            }
            
            console.log('无法将按钮添加到目标元素,使用默认位置');
            createButtonAtDefault();
            return false;
            
        } catch (e) {
            console.error('在目标位置创建按钮失败:', e);
            console.log('使用默认位置创建按钮');
            createButtonAtDefault();
            return false;
        }
    }
    
    // 在默认位置创建按钮
    function createButtonAtDefault() {
        const btn = document.createElement('button');
        btn.className = 'group-counter-btn';
        btn.textContent = '统计分组产品数';
        btn.onclick = showGroupCounter;
        document.body.appendChild(btn);
        console.log('按钮已添加到默认位置');
    }

    // 启动脚本
    init();
    
    // 调试按钮查找问题
    function debugButtonPlacement() {}
    
    // 调试页面结构函数
    function debugPageStructure() {}
    
    // 调试产品数量获取问题
    async function debugProductCount() {}
    
    // 改进的产品数量获取函数
    // 改进的产品数量获取函数 - 智能检测可用模块,增加重试和调试
    async function getImprovedProductCount(groupUrl, targetPcTitle) {
        const maxRetries = 3;
        let retryCount = 0;
        
        while (retryCount < maxRetries) {
            try {
                // 确保URL被正确清理,移除所有查询参数
                const cleanUrl = sanitizeListingUrl(groupUrl);
                console.log(`正在获取分组产品数量 (第${retryCount + 1}次尝试): ${cleanUrl}`);
                console.log(`原始URL: ${groupUrl}`);
                
                // 添加随机延迟 - 严格按照Python代码的延迟时间 (0.5-1.3秒)
                const delay = Math.random() * 800 + 500;
                console.log(`等待延迟: ${delay}ms`);
                await new Promise(resolve => setTimeout(resolve, delay));
                
                // 使用更完整的请求头,模拟真实浏览器
                const response = await fetch(cleanUrl, {
                    method: 'GET',
                    headers: {
                        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
                        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Connection': 'keep-alive',
                        'Upgrade-Insecure-Requests': '1',
                        'Sec-Fetch-Dest': 'document',
                        'Sec-Fetch-Mode': 'navigate',
                        'Sec-Fetch-Site': 'same-origin',
                        'Cache-Control': 'max-age=0'
                    },
                    mode: 'same-origin',
                    credentials: 'include'
                });
                
                if (!response.ok) {
                    console.error(`HTTP错误: ${response.status} ${response.statusText} - ${cleanUrl}`);
                    if (response.status === 404) {
                        console.log('页面不存在,返回0');
                        return 0;
                    }
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const html = await response.text();
                console.log(`页面大小: ${html.length} 字符`);
                
                if (html.length < 1000) {
                    console.warn('页面内容过短,可能加载失败');
                    console.log('页面内容预览:', html.substring(0, 500));
                }
                
                // 查找module-data - 使用更精确的正则表达式
                const matches = html.match(/module-data=(["\'])(.*?)\1/g);
                if (!matches || matches.length === 0) {
                    console.log(`页面 ${cleanUrl} 未找到module-data`);
                    console.log('页面内容预览:', html.substring(0, 1000));
                    return 0;
                }
                
                console.log(`页面 ${cleanUrl} 找到 ${matches.length} 个module-data`);
                
                // 首先尝试查找目标模块(如果指定了的话)
                if (targetPcTitle) {
                    console.log(`尝试查找目标模块: ${targetPcTitle}`);
                    for (let i = 0; i < matches.length; i++) {
                        try {
                            const moduleDataStr = matches[i].match(/module-data=(["\'])(.*?)\1/)[2];
                            const decoded = decodeURIComponent(moduleDataStr);
                            const dataJson = JSON.parse(decoded);
                            const moduleTitle = findModuleTitle(dataJson);
                            
                            console.log(`模块 ${i + 1} 标题: ${moduleTitle}`);
                            
                            if (moduleTitle === targetPcTitle) {
                                console.log(`找到目标模块 ${targetPcTitle}`);
                                const count = extractProductCountFromModule(dataJson);
                                if (count > 0) {
                                    console.log(`从目标模块获取到产品数量: ${count}`);
                                    return count;
                                }
                            }
                        } catch (e) {
                            console.error(`解析模块 ${i + 1} 失败:`, e);
                            continue;
                        }
                    }
                    console.log(`未找到目标模块 ${targetPcTitle} 或产品数量为0`);
                }
                
                // 智能检测:查找任何可能包含产品数量的模块
                console.log('开始智能检测包含产品数量的模块...');
                const allModules = [];
                
                for (let i = 0; i < matches.length; i++) {
                    try {
                        const moduleDataStr = matches[i].match(/module-data=(["\'])(.*?)\1/)[2];
                        const decoded = decodeURIComponent(moduleDataStr);
                        const dataJson = JSON.parse(decoded);
                        const moduleTitle = findModuleTitle(dataJson);
                        
                        allModules.push({
                            index: i + 1,
                            title: moduleTitle || `未知模块${i + 1}`,
                            data: dataJson
                        });
                        
                        // 检查这个模块是否包含产品数量
                        const count = extractProductCountFromModule(dataJson);
                        if (count > 0) {
                            console.log(`在模块 ${i + 1} (${moduleTitle || '未知标题'}) 中找到产品数量: ${count}`);
                            return count;
                        }
                    } catch (e) {
                        console.error(`解析模块 ${i + 1} 失败:`, e);
                        continue;
                    }
                }
                
                // 如果还是没有找到,记录所有模块信息用于调试
                console.log('所有模块信息:', allModules.map(m => `${m.index}: ${m.title}`));
                console.log(`页面 ${cleanUrl} 未找到任何包含产品数量的模块`);
                
                return 0;
                
            } catch (e) {
                retryCount++;
                console.error(`获取分组产品数量失败 (第${retryCount}次): ${cleanUrl} - ${e}`);
                console.log('错误详情:', e.stack);
                
                if (retryCount >= maxRetries) {
                    console.error(`达到最大重试次数,返回错误状态`);
                    return -1;
                }
                
                // 等待后重试
                const retryDelay = Math.random() * 1000 + 1000; // 1-2秒
                console.log(`等待 ${retryDelay}ms 后重试...`);
                await new Promise(resolve => setTimeout(resolve, retryDelay));
            }
        }
        
        return -1;
    }
    
    // 从模块数据中提取产品数量的辅助函数
    function extractProductCountFromModule(dataJson) {
        try {
            let totalLines = 0;
            
            // 严格按照Python代码的逻辑获取产品数量
            if (dataJson.mds && dataJson.mds.moduleData && dataJson.mds.moduleData.data) {
                const data = dataJson.mds.moduleData.data;
                console.log(`模块数据结构:`, data);
                console.log(`可用字段:`, Object.keys(data));
                
                // 严格按照Python代码的逻辑获取产品数量
                if (data.pageNavView && data.pageNavView.totalLines) {
                    totalLines = data.pageNavView.totalLines;
                    console.log(`从 pageNavView.totalLines 获取到数量: ${totalLines}`);
                } else if (data.totalLines) {
                    totalLines = data.totalLines;
                    console.log(`从 totalLines 获取到数量: ${totalLines}`);
                } else if (data.total) {
                    totalLines = data.total;
                    console.log(`从 total 获取到数量: ${totalLines}`);
                } else {
                    console.log(`未找到产品数量字段,详细数据结构:`, data);
                    
                    // 尝试查找其他可能包含数量的字段
                    for (const key in data) {
                        const value = data[key];
                        if (typeof value === 'number' && value > 0 && value < 100000) {
                            console.log(`发现可能的数量字段 ${key}: ${value}`);
                            // 如果找到看起来像产品数量的字段,使用它
                            if (key.toLowerCase().includes('total') || key.toLowerCase().includes('count') || key.toLowerCase().includes('line')) {
                                totalLines = value;
                                console.log(`使用可能的数量字段 ${key}: ${value}`);
                                break;
                            }
                        }
                    }
                }
            } else {
                console.log('未找到 mds.moduleData.data 路径');
                console.log('dataJson.mds:', dataJson.mds);
                if (dataJson.mds) {
                    console.log('dataJson.mds.moduleData:', dataJson.mds.moduleData);
                }
                
                // 尝试直接从根级别查找
                if (dataJson.totalLines) {
                    totalLines = dataJson.totalLines;
                    console.log(`从根级别 totalLines 获取到数量: ${totalLines}`);
                } else if (dataJson.total) {
                    totalLines = dataJson.total;
                    console.log(`从根级别 total 获取到数量: ${totalLines}`);
                } else if (dataJson.count) {
                    totalLines = dataJson.count;
                    console.log(`从根级别 count 获取到数量: ${totalLines}`);
                } else if (dataJson.productCount) {
                    totalLines = dataJson.productCount;
                    console.log(`从根级别 productCount 获取到数量: ${totalLines}`);
                } else if (dataJson.productNum) {
                    totalLines = dataJson.productNum;
                    console.log(`从根级别 productNum 获取到数量: ${totalLines}`);
                }
                
                // 尝试从其他可能的结构中查找
                if (totalLines === 0 && dataJson.data && typeof dataJson.data === 'object') {
                    const data = dataJson.data;
                    if (data.totalLines) {
                        totalLines = data.totalLines;
                        console.log(`从 data.totalLines 获取到数量: ${totalLines}`);
                    } else if (data.total) {
                        totalLines = data.total;
                        console.log(`从 data.total 获取到数量: ${totalLines}`);
                    } else if (data.count) {
                        totalLines = data.count;
                        console.log(`从 data.count 获取到数量: ${totalLines}`);
                    } else if (data.productCount) {
                        totalLines = data.productCount;
                        console.log(`从 data.productCount 获取到数量: ${totalLines}`);
                    }
                }
            }
            
            return totalLines;
        } catch (e) {
            console.error('提取产品数量时出错:', e);
            console.log('错误详情:', e.stack);
            return 0;
        }
    }
    
    // 增强的产品数量调试函数 - 深入分析页面结构和module-data
    async function enhancedDebugProductCount() {
        console.log('=== 开始增强调试产品数量获取问题 ===');
        
        const groupList = document.getElementById('group-list');
        if (groupList) {
            groupList.innerHTML = '<p>正在深入调试产品数量获取...</p>';
        }
        
        try {
            // 获取当前页面URL
            const currentUrl = window.location.href;
            let baseUrl = currentUrl;
            if (baseUrl.includes('/productlist.html')) {
                baseUrl = baseUrl.replace('/productlist.html', '');
            } else if (baseUrl.includes('/featureproductlist-')) {
                baseUrl = baseUrl.replace(/\/featureproductlist-\d+\.html/, '');
            } else if (baseUrl.includes('/productgrouplist-')) {
                baseUrl = baseUrl.replace(/\/productgrouplist-\d+.*/, '');
            }
            
            console.log('店铺基础URL:', baseUrl);
            
            // 测试全店产品数量获取
            console.log('测试全店产品数量获取...');
            const allStoreUrl = baseUrl + '/productlist.html';
            console.log('测试URL:', allStoreUrl);
            
            // 首先分析页面结构
            const pageAnalysis = await analyzePageStructure(allStoreUrl);
            console.log('页面结构分析结果:', pageAnalysis);
            
            // 测试产品数量获取
            const allStoreCount = await getImprovedProductCount(allStoreUrl, "PC产品列表");
            console.log('全店产品数量结果:', allStoreCount);
            
            // 显示调试结果
            if (groupList) {
                let debugHtml = '<div class="debug-info">';
                debugHtml += '<h4>增强调试结果</h4>';
                debugHtml += `<p>店铺基础URL: ${baseUrl}</p>`;
                debugHtml += `<p>全店产品URL: ${allStoreUrl}</p>`;
                debugHtml += `<p>全店产品数量: ${allStoreCount === -1 ? '获取失败' : allStoreCount}</p>`;
                debugHtml += '<h5>页面结构分析:</h5>';
                debugHtml += `<p>找到的模块数量: ${pageAnalysis.moduleCount}</p>`;
                debugHtml += `<p>模块标题列表: ${pageAnalysis.moduleTitles.join(', ')}</p>`;
                debugHtml += `<p>包含产品数量的模块: ${pageAnalysis.productCountModules.join(', ')}</p>`;
                debugHtml += '<h5>详细分析:</h5>';
                debugHtml += `<pre style="max-height: 200px; overflow-y: auto; background: #f5f5f5; padding: 10px; font-size: 12px;">${JSON.stringify(pageAnalysis.detailedInfo, null, 2)}</pre>`;
                debugHtml += '<button class="retry-btn" onclick="enhancedDebugProductCount()">重新调试</button>';
                debugHtml += '<button class="retry-btn" onclick="analyzeGroups()">开始分析分组</button>';
                debugHtml += '</div>';
                
                groupList.innerHTML = debugHtml;
            }
            
        } catch (e) {
            console.error('增强调试失败:', e);
            if (groupList) {
                groupList.innerHTML = `<p style="color: red;">增强调试失败: ${e.message}</p>`;
            }
        }
        
        console.log('=== 增强调试完成 ===');
    }
    
    // 分析页面结构的函数
    async function analyzePageStructure(url) {
        try {
            console.log(`分析页面结构: ${url}`);
            
            const response = await fetch(url, {
                method: 'GET',
                headers: {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
                    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'Connection': 'keep-alive',
                    'Upgrade-Insecure-Requests': '1',
                    'Sec-Fetch-Dest': 'document',
                    'Sec-Fetch-Mode': 'navigate',
                    'Sec-Fetch-Site': 'same-origin',
                    'Cache-Control': 'max-age=0'
                },
                mode: 'same-origin',
                credentials: 'include'
            });
            
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const html = await response.text();
            console.log(`页面大小: ${html.length} 字符`);
            
            // 查找所有module-data
            const matches = html.match(/module-data=(["\'])(.*?)\1/g);
            if (!matches || matches.length === 0) {
                return {
                    moduleCount: 0,
                    moduleTitles: [],
                    productCountModules: [],
                    detailedInfo: { error: '未找到module-data' }
                };
            }
            
            console.log(`找到 ${matches.length} 个module-data`);
            
            const moduleTitles = [];
            const productCountModules = [];
            const detailedInfo = {};
            
            // 分析每个模块
            for (let i = 0; i < matches.length; i++) {
                try {
                    const moduleDataStr = matches[i].match(/module-data=(["\'])(.*?)\1/)[2];
                    const decoded = decodeURIComponent(moduleDataStr);
                    const dataJson = JSON.parse(decoded);
                    const moduleTitle = findModuleTitle(dataJson);
                    
                    if (moduleTitle) {
                        moduleTitles.push(moduleTitle);
                        detailedInfo[`模块${i + 1}_${moduleTitle}`] = {
                            title: moduleTitle,
                            structure: analyzeDataStructure(dataJson),
                            hasProductCount: checkForProductCount(dataJson)
                        };
                        
                        if (checkForProductCount(dataJson)) {
                            productCountModules.push(moduleTitle);
                        }
                    }
                } catch (e) {
                    console.error(`解析模块 ${i + 1} 失败:`, e);
                    detailedInfo[`模块${i + 1}_解析失败`] = { error: e.message };
                }
            }
            
            return {
                moduleCount: matches.length,
                moduleTitles: moduleTitles,
                productCountModules: productCountModules,
                detailedInfo: detailedInfo
            };
            
        } catch (e) {
            console.error('分析页面结构失败:', e);
            return {
                moduleCount: 0,
                moduleTitles: [],
                productCountModules: [],
                detailedInfo: { error: e.message }
            };
        }
    }
    
    // 分析数据结构
    function analyzeDataStructure(obj, maxDepth = 3, currentDepth = 0) {
        if (currentDepth >= maxDepth) {
            return '达到最大深度';
        }
        
        if (typeof obj === 'object' && obj !== null) {
            const result = {};
            for (const key in obj) {
                if (obj.hasOwnProperty(key)) {
                    const value = obj[key];
                    if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
                        result[key] = analyzeDataStructure(value, maxDepth, currentDepth + 1);
                    } else if (Array.isArray(value)) {
                        result[key] = `数组[${value.length}]`;
                    } else {
                        result[key] = typeof value;
                    }
                }
            }
            return result;
        }
        
        return typeof obj;
    }
    
    // 检查是否包含产品数量信息 - 增强版本
    function checkForProductCount(obj) {
        if (typeof obj === 'object' && obj !== null) {
            // 检查常见的产品数量字段
            if (obj.totalLines || obj.total || obj.count) {
                return true;
            }
            
            // 检查嵌套结构
            if (obj.mds && obj.mds.moduleData && obj.mds.moduleData.data) {
                const data = obj.mds.moduleData.data;
                if (data.pageNavView && data.pageNavView.totalLines) {
                    return true;
                }
                if (data.totalLines || data.total || data.count) {
                    return true;
                }
                
                // 检查更多可能的产品数量字段
                if (data.productCount || data.productNum || data.itemCount || data.itemNum) {
                    return true;
                }
                
                // 检查产品列表长度
                if (data.productList && Array.isArray(data.productList) && data.productList.length > 0) {
                    return true;
                }
                if (data.products && Array.isArray(data.products) && data.products.length > 0) {
                    return true;
                }
            }
            
            // 检查其他可能的结构
            if (obj.data && typeof obj.data === 'object') {
                const data = obj.data;
                if (data.totalLines || data.total || data.count || data.productCount) {
                    return true;
                }
                if (data.productList && Array.isArray(data.productList) && data.productList.length > 0) {
                    return true;
                }
            }
            
            // 递归检查
            for (const key in obj) {
                if (obj.hasOwnProperty(key) && typeof obj[key] === 'object') {
                    if (checkForProductCount(obj[key])) {
                        return true;
                    }
                }
            }
        }
        
        return false;
    }

    // 仅暴露必要函数
    window.analyzeGroups = analyzeGroups;

    // 增强的产品数量调试函数 - 深入分析页面结构和module-data
    async function enhancedDebugProductCount() {
        console.log('=== 开始增强调试产品数量获取问题 ===');
        
        const groupList = document.getElementById('group-list');
        if (groupList) {
            groupList.innerHTML = '<p>正在深入调试产品数量获取...</p>';
        }
        
        try {
            // 获取当前页面URL
            const currentUrl = window.location.href;
            let baseUrl = currentUrl;
            if (baseUrl.includes('/productlist.html')) {
                baseUrl = baseUrl.replace('/productlist.html', '');
            } else if (baseUrl.includes('/featureproductlist-')) {
                baseUrl = baseUrl.replace(/\/featureproductlist-\d+\.html/, '');
            } else if (baseUrl.includes('/productgrouplist-')) {
                baseUrl = baseUrl.replace(/\/productgrouplist-\d+.*/, '');
            }
            
            console.log('店铺基础URL:', baseUrl);
            
            // 测试全店产品数量获取
            console.log('测试全店产品数量获取...');
            const allStoreUrl = baseUrl + '/productlist.html';
            console.log('测试URL:', allStoreUrl);
            
            // 首先分析页面结构
            const pageAnalysis = await analyzePageStructure(allStoreUrl);
            console.log('页面结构分析结果:', pageAnalysis);
            
            // 测试产品数量获取
            const allStoreCount = await getImprovedProductCount(allStoreUrl, "PC产品列表");
            console.log('全店产品数量结果:', allStoreCount);
            
            // 显示调试结果
            if (groupList) {
                let debugHtml = '<div class="debug-info">';
                debugHtml += '<h4>增强调试结果</h4>';
                debugHtml += `<p>店铺基础URL: ${baseUrl}</p>`;
                debugHtml += `<p>全店产品URL: ${allStoreUrl}</p>`;
                debugHtml += `<p>全店产品数量: ${allStoreCount === -1 ? '获取失败' : allStoreCount}</p>`;
                debugHtml += '<h5>页面结构分析:</h5>';
                debugHtml += `<p>找到的模块数量: ${pageAnalysis.moduleCount}</p>`;
                debugHtml += `<p>模块标题列表: ${pageAnalysis.moduleTitles.join(', ')}</p>`;
                debugHtml += `<p>包含产品数量的模块: ${pageAnalysis.productCountModules.join(', ')}</p>`;
                debugHtml += '<h5>详细分析:</h5>';
                debugHtml += `<pre style="max-height: 200px; overflow-y: auto; background: #f5f5f5; padding: 10px; font-size: 12px;">${JSON.stringify(pageAnalysis.detailedInfo, null, 2)}</pre>`;
                debugHtml += '<button class="retry-btn" onclick="enhancedDebugProductCount()">重新调试</button>';
                debugHtml += '<button class="retry-btn" onclick="analyzeGroups()">开始分析分组</button>';
                debugHtml += '</div>';
                
                groupList.innerHTML = debugHtml;
            }
            
        } catch (e) {
            console.error('增强调试失败:', e);
            if (groupList) {
                groupList.innerHTML = `<p style="color: red;">增强调试失败: ${e.message}</p>`;
            }
        }
        
        console.log('=== 增强调试完成 ===');
    }
    
    // 分析页面结构的函数
    async function analyzePageStructure(url) {
        try {
            console.log(`分析页面结构: ${url}`);
            
            const response = await fetch(url, {
                method: 'GET',
                headers: {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
                    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'Connection': 'keep-alive',
                    'Upgrade-Insecure-Requests': '1',
                    'Sec-Fetch-Dest': 'document',
                    'Sec-Fetch-Mode': 'navigate',
                    'Sec-Fetch-Site': 'same-origin',
                    'Cache-Control': 'max-age=0'
                },
                mode: 'same-origin',
                credentials: 'include'
            });
            
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const html = await response.text();
            console.log(`页面大小: ${html.length} 字符`);
            
            // 查找所有module-data
            const matches = html.match(/module-data=(["\'])(.*?)\1/g);
            if (!matches || matches.length === 0) {
                return {
                    moduleCount: 0,
                    moduleTitles: [],
                    productCountModules: [],
                    detailedInfo: { error: '未找到module-data' }
                };
            }
            
            console.log(`找到 ${matches.length} 个module-data`);
            
            const moduleTitles = [];
            const productCountModules = [];
            const detailedInfo = {};
            
            // 分析每个模块
            for (let i = 0; i < matches.length; i++) {
                try {
                    const moduleDataStr = matches[i].match(/module-data=(["\'])(.*?)\1/)[2];
                    const decoded = decodeURIComponent(moduleDataStr);
                    const dataJson = JSON.parse(decoded);
                    const moduleTitle = findModuleTitle(dataJson);
                    
                    if (moduleTitle) {
                        moduleTitles.push(moduleTitle);
                        detailedInfo[`模块${i + 1}_${moduleTitle}`] = {
                            title: moduleTitle,
                            structure: analyzeDataStructure(dataJson),
                            hasProductCount: checkForProductCount(dataJson)
                        };
                        
                        if (checkForProductCount(dataJson)) {
                            productCountModules.push(moduleTitle);
                        }
                    }
                } catch (e) {
                    console.error(`解析模块 ${i + 1} 失败:`, e);
                    detailedInfo[`模块${i + 1}_解析失败`] = { error: e.message };
                }
            }
            
            return {
                moduleCount: matches.length,
                moduleTitles: moduleTitles,
                productCountModules: productCountModules,
                detailedInfo: detailedInfo
            };
            
        } catch (e) {
            console.error('分析页面结构失败:', e);
            return {
                moduleCount: 0,
                moduleTitles: [],
                productCountModules: [],
                detailedInfo: { error: e.message }
            };
        }
    }
    
    // 分析数据结构
    function analyzeDataStructure(obj, maxDepth = 3, currentDepth = 0) {
        if (currentDepth >= maxDepth) {
            return '达到最大深度';
        }
        
        if (typeof obj === 'object' && obj !== null) {
            const result = {};
            for (const key in obj) {
                if (obj.hasOwnProperty(key)) {
                    const value = obj[key];
                    if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
                        result[key] = analyzeDataStructure(value, maxDepth, currentDepth + 1);
                    } else if (Array.isArray(value)) {
                        result[key] = `数组[${value.length}]`;
                    } else {
                        result[key] = typeof value;
                    }
                }
            }
            return result;
        }
        
        return typeof obj;
    }
    
})();