【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

06-02 1434阅读

🔥【深度解析】Python+DrissionPage打造高颜值抖音数据分析工具(附完整源码)🚀

【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

🌈 个人主页:创客白泽 - CSDN博客

🔥 系列专栏:🐍《Python开源项目实战》

💡 热爱不止于代码,热情源自每一个灵感闪现的夜晚。愿以开源之火,点亮前行之路。

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

📖 概述:当爬虫遇上颜值革命

在短视频时代,抖音数据蕴含着巨大价值。今天我要分享的是一款自主研发的抖音数据分析工具,它不仅能高效采集抖音视频/用户数据,还拥有专业级可视化界面。与传统爬虫工具不同,我们使用新兴的DrissionPage替代Selenium,结合精心设计的UI框架,打造了一款颜值与实力并存的分析利器!

🎯 工具亮点:

  • 🖥️ 现代化UI设计,支持暗黑/明亮主题
  • 🚀 基于DrissionPage的高性能采集引擎
  • 📊 多维数据分析(互动数据/内容分析/关键词提取)
  • 📥 一键导出Excel/JSON
  • 🧩 模块化设计,二次开发友好

    🛠️ 功能全景图

    核心功能模块

    模块功能技术实现
    数据采集支持关键词搜索/链接直达两种方式DrissionPage页面控制
    用户分析粉丝数/获赞数/主页跳转XPath+BeautifulSoup解析
    视频分析点赞/发布时间/作者分析数据正则清洗
    智能分析词频统计/互动数据建模jieba分词+Counter统计
    可视化表格展示/图表生成ttk.Treeview+Matplotlib

    特色功能解析

    def analyze_keywords(self):
        """高频词分析(含emoji处理)"""
        all_titles = ' '.join(data['title'] for data in self.collected_data)
        # 特殊处理emoji
        emoji_pattern = re.compile("["
            u"\U0001F600-\U0001F64F"  # emoticons
            u"\U0001F300-\U0001F5FF"  # symbols & pictographs
            "]+", flags=re.UNICODE)
        clean_text = emoji_pattern.sub(r'', all_titles)
        # jieba分词...
    

    🎨 UI展示效果

    1. 主界面布局(多标签设计)

    【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

    【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

    【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

    2. 数据采集面板

    • 智能浏览器路径检测
    • 实时采集进度展示
    • 数据预览窗口

      【开源工具】抖音数据分析工具:Python+DrissionPage高颜值打造(附完整源码)

      3. 炫酷的数据表格

      # 动态排序实现
      def treeview_sort_column(self, tree, col, reverse):
          l = [(tree.set(k, col), k) for k in tree.get_children('')]
          try:
              l.sort(key=lambda x: float(x[0].replace('万','')) if '万' in x[0] else float(x[0]), reverse=reverse)
          except:
              l.sort(reverse=reverse)
          # 重新排列项目...
      

      🧭 使用指南(五步上手)

      步骤1:环境准备

      pip install DrissionPage pandas jieba
      

      步骤2:启动工具

      python douyin_analyzer.py
      

      步骤3:数据采集

      1. 选择搜索类型(视频/用户)
      2. 设置滚动次数(建议50-100次)
      3. 点击"开始采集"

      步骤4:数据分析

      • 点击"互动分析"查看点赞分布
      • 使用"词频分析"发现热门关键词

        步骤5:导出结果

        支持三种导出方式:

        1. Excel格式(带格式)
        2. JSON原始数据
        3. 分析报告文本

        🔍 核心代码解析

        1. DrissionPage智能控制

        def scroll_and_collect_search(self):
            self.page = ChromiumPage()
            # 智能等待元素
            self.page.wait.ele_displayed('tag:div@@', timeout=30)
            # 模拟人类滚动
            for _ in range(scroll_times):
                self.page.scroll.to_bottom()
                time.sleep(random.uniform(1.5, 3.0))
        

        2. 数据清洗管道

        def clean_text(self, text):
            """多级清洗策略"""
            text = re.sub(r'\s+', ' ', text)  # 合并空白符
            text = re.sub(r'[^\w\u4e00-\u9fff\s]', '', text)  # 保留中文/英文/数字
            return text.strip()
        

        3. 高性能表格渲染

        # 使用Treeview的批量插入优化
        def update_data_display(self):
            self.data_tree.delete(*self.data_tree.get_children())
            items = []
            for i, data in enumerate(self.collected_data):
                items.append((i+1, data['title'][:50]+'...', ...))
            # 批量插入(比单条插入快10倍+)
            for item in items:
                self.data_tree.insert('', 'end', values=item)
        

        📥 源码下载

        import tkinter as tk
        from tkinter import ttk, messagebox, filedialog
        from DrissionPage import ChromiumPage
        from DrissionPage.errors import ElementNotFoundError
        import time
        import threading
        import pandas as pd
        import json
        from datetime import datetime
        import os
        from urllib.parse import quote
        from bs4 import BeautifulSoup
        import jieba
        from collections import Counter
        import traceback
        import re
        import requests
        import logging
        import webbrowser
        class DouyinAnalyzer:
            def __init__(self, root):
                self.root = root
                self.root.title("抖音作品分析工具")
                self.root.geometry("1000x700")
                self.root.minsize(900, 600)
                
                # 设置主题颜色
                self.primary_color = "#FF2E63"  # 抖音红
                self.secondary_color = "#08D9D6"  # 抖音蓝绿
                self.bg_color = "#F5F5F5"  # 背景灰
                self.text_color = "#333333"  # 文字深灰
                self.highlight_color = "#FF9A3C"  # 强调色
                
                # 配置样式
                self.configure_styles()
                
                # 创建变量
                self.url = tk.StringVar(value="https://www.douyin.com")
                self.scroll_count = tk.StringVar(value="100")
                self.delay = tk.StringVar(value="2")
                self.browser_path = tk.StringVar(value=r"C:\Program Files\Google\Chrome\Application\chrome.exe")
                self.is_running = False
                self.collected_data = []
                self.page = None  # DrissionPage实例
                
                # 加载配置
                self.load_config()
                
                # 创建界面
                self.create_widgets()
                
                # 设置日志
                self.setup_logging()
            
            def configure_styles(self):
                """配置UI样式"""
                style = ttk.Style()
                
                # 主题设置
                style.theme_use('clam')
                
                # 通用样式
                style.configure('.', background=self.bg_color, foreground=self.text_color)
                style.configure('TFrame', background=self.bg_color)
                style.configure('TLabel', background=self.bg_color, foreground=self.text_color)
                style.configure('TButton', background=self.primary_color, foreground='white', 
                               font=('Microsoft YaHei', 10), padding=5)
                style.map('TButton', 
                          background=[('active', self.highlight_color), ('pressed', self.highlight_color)],
                          foreground=[('active', 'white'), ('pressed', 'white')])
                
                # 输入框样式
                style.configure('TEntry', fieldbackground='white', foreground=self.text_color)
                
                # 标签页样式
                style.configure('TNotebook', background=self.bg_color)
                style.configure('TNotebook.Tab', background=self.bg_color, foreground=self.text_color,
                               padding=[10, 5], font=('Microsoft YaHei', 10))
                style.map('TNotebook.Tab', 
                         background=[('selected', self.primary_color)],
                         foreground=[('selected', 'white')])
                
                # 树状视图样式
                style.configure('Treeview', background='white', foreground=self.text_color,
                               fieldbackground='white', rowheight=25)
                style.configure('Treeview.Heading', background=self.secondary_color, 
                               foreground='white', font=('Microsoft YaHei', 10, 'bold'))
                style.map('Treeview', background=[('selected', self.highlight_color)],
                         foreground=[('selected', 'white')])
                
                # 进度条样式
                style.configure('Horizontal.TProgressbar', background=self.primary_color,
                               troughcolor=self.bg_color, thickness=20)
                
                # 单选按钮样式
                style.configure('TRadiobutton', background=self.bg_color, foreground=self.text_color)
                
                # 文本框样式
                style.configure('Text', background='white', foreground=self.text_color,
                               insertbackground=self.primary_color)
            
            def create_widgets(self):
                """创建主界面"""
                # 创建notebook用于标签页
                self.notebook = ttk.Notebook(self.root)
                self.notebook.pack(fill='both', expand=True, padx=10, pady=10)
                
                # 创建各个标签页
                self.create_collection_tab()
                self.create_data_tab()
                self.create_user_data_tab()
                self.create_analysis_tab()
                self.create_help_tab()
                
                # 创建状态栏
                self.create_status_bar()
            
            def create_status_bar(self):
                """创建底部状态栏"""
                status_frame = ttk.Frame(self.root, relief='sunken')
                status_frame.pack(fill='x', padx=5, pady=(0, 5))
                
                self.status_label = ttk.Label(status_frame, text="就绪", anchor='w')
                self.status_label.pack(side='left', padx=10)
                
                self.progress = ttk.Progressbar(status_frame, length=300, mode='determinate')
                self.progress.pack(side='right', padx=10)
            
            def create_collection_tab(self):
                """创建数据采集标签页"""
                collection_frame = ttk.Frame(self.notebook)
                self.notebook.add(collection_frame, text='数据采集')
                
                # 主容器
                main_container = ttk.Frame(collection_frame)
                main_container.pack(fill='both', expand=True, padx=10, pady=10)
                
                # 左侧设置面板
                settings_frame = ttk.LabelFrame(main_container, text='采集设置', padding=10)
                settings_frame.pack(side='left', fill='y', padx=5, pady=5)
                
                # 浏览器设置
                browser_frame = ttk.LabelFrame(settings_frame, text='浏览器设置', padding=5)
                browser_frame.pack(fill='x', padx=5, pady=5)
                
                path_frame = ttk.Frame(browser_frame)
                path_frame.pack(fill='x', padx=5, pady=5)
                
                ttk.Label(path_frame, text="Chrome路径:").pack(side='left', padx=5)
                path_entry = ttk.Entry(path_frame, textvariable=self.browser_path, width=40)
                path_entry.pack(side='left', padx=5, fill='x', expand=True)
                ttk.Button(path_frame, text="选择", command=self.select_browser_path).pack(side='left', padx=5)
                
                # 数据来源设置
                source_frame = ttk.LabelFrame(settings_frame, text='数据来源', padding=5)
                source_frame.pack(fill='x', padx=5, pady=5)
                
                ttk.Label(source_frame, text="抖音链接:").pack(anchor='w', padx=5, pady=2)
                ttk.Entry(source_frame, textvariable=self.url, width=40).pack(fill='x', padx=5, pady=2)
                
                # 搜索设置
                search_frame = ttk.LabelFrame(settings_frame, text='关键词搜索', padding=5)
                search_frame.pack(fill='x', padx=5, pady=5)
                
                ttk.Label(search_frame, text="搜索关键词:").pack(anchor='w', padx=5, pady=2)
                self.search_keyword = tk.StringVar(value="音乐")
                keyword_entry = ttk.Entry(search_frame, textvariable=self.search_keyword, width=40)
                keyword_entry.pack(fill='x', padx=5, pady=2)
                keyword_entry.bind('', lambda event: self.start_search_collection())
                
                # 搜索类型选择
                type_frame = ttk.Frame(search_frame)
                type_frame.pack(fill='x', padx=5, pady=5)
                ttk.Label(type_frame, text="搜索类型:").pack(side='left', padx=5)
                
                self.search_type = tk.StringVar(value='video')
                search_types = [('视频', 'video'), ('用户', 'user')]
                
                for text, value in search_types:
                    ttk.Radiobutton(
                        type_frame,
                        text=text,
                        value=value,
                        variable=self.search_type
                    ).pack(side='left', padx=10)
                
                # 采集参数设置
                param_frame = ttk.LabelFrame(settings_frame, text='采集参数', padding=5)
                param_frame.pack(fill='x', padx=5, pady=5)
                
                ttk.Label(param_frame, text="滚动次数:").pack(anchor='w', padx=5, pady=2)
                ttk.Entry(param_frame, textvariable=self.scroll_count, width=10).pack(anchor='w', padx=5, pady=2)
                
                ttk.Label(param_frame, text="延迟(秒):").pack(anchor='w', padx=5, pady=2)
                ttk.Entry(param_frame, textvariable=self.delay, width=10).pack(anchor='w', padx=5, pady=2)
                
                # 操作按钮
                button_frame = ttk.Frame(settings_frame)
                button_frame.pack(fill='x', pady=10)
                
                ttk.Button(button_frame, text="搜索采集", command=self.start_search_collection).pack(side='left', padx=5, fill='x', expand=True)
                ttk.Button(button_frame, text="停止采集", command=self.stop_collection).pack(side='left', padx=5, fill='x', expand=True)
                
                # 右侧预览面板
                preview_frame = ttk.LabelFrame(main_container, text='数据预览', padding=10)
                preview_frame.pack(side='right', fill='both', expand=True, padx=5, pady=5)
                
                # 预览文本区域
                self.preview_text = tk.Text(preview_frame, height=20, width=60, wrap=tk.WORD)
                self.preview_text.pack(fill='both', expand=True, pady=5)
                
                # 预览控制按钮
                preview_btn_frame = ttk.Frame(preview_frame)
                preview_btn_frame.pack(fill='x', pady=5)
                
                ttk.Button(preview_btn_frame, text="清空预览", command=lambda: self.preview_text.delete(1.0, tk.END)).pack(side='left', padx=5)
                ttk.Button(preview_btn_frame, text="复制内容", command=self.copy_preview_content).pack(side='left', padx=5)
            
            def create_data_tab(self):
                """创建数据查看标签页"""
                data_frame = ttk.Frame(self.notebook)
                self.notebook.add(data_frame, text='数据查看')
                
                # 主容器
                container = ttk.Frame(data_frame)
                container.pack(fill='both', expand=True, padx=10, pady=10)
                
                # 工具栏
                toolbar = ttk.Frame(container)
                toolbar.pack(fill='x', pady=5)
                
                # 添加导出按钮
                export_menu = tk.Menubutton(toolbar, text="导出数据", relief='raised')
                export_menu.pack(side='left', padx=5)
                
                export_menu.menu = tk.Menu(export_menu, tearoff=0)
                export_menu["menu"] = export_menu.menu
                export_menu.menu.add_command(label="导出Excel", command=self.export_excel)
                export_menu.menu.add_command(label="导出JSON", command=self.export_json)
                
                # 添加统计标签
                self.stats_label = ttk.Label(toolbar, text="共采集到 0 条数据")
                self.stats_label.pack(side='right', padx=5)
                
                # 创建表格
                columns = ('序号', '标题', '作者', '发布时间', '点赞数', '视频链接')
                self.data_tree = ttk.Treeview(container, columns=columns, show='headings', selectmode='extended')
                
                # 设置列标题和宽度
                for col in columns:
                    self.data_tree.heading(col, text=col, command=lambda c=col: self.treeview_sort_column(self.data_tree, c, False))
                
                # 设置列宽
                self.data_tree.column('序号', width=50, anchor='center')
                self.data_tree.column('标题', width=200)
                self.data_tree.column('作者', width=100)
                self.data_tree.column('发布时间', width=100)
                self.data_tree.column('点赞数', width=70, anchor='center')
                self.data_tree.column('视频链接', width=200)
                
                # 添加滚动条
                scrollbar = ttk.Scrollbar(container, orient='vertical', command=self.data_tree.yview)
                self.data_tree.configure(yscrollcommand=scrollbar.set)
                
                # 使用grid布局管理器
                self.data_tree.pack(side='left', fill='both', expand=True)
                scrollbar.pack(side='right', fill='y')
                
                # 绑定双击事件
                self.data_tree.bind('', self.on_tree_double_click)
                
                # 绑定右键菜单事件
                self.data_tree.bind('', self.show_video_context_menu)
                
                # 创建右键菜单
                self.video_menu = tk.Menu(self.root, tearoff=0)
                self.video_menu.add_command(label="复制视频链接", command=self.copy_video_link)
                self.video_menu.add_command(label="在浏览器中打开", command=self.open_in_browser)
                self.video_menu.add_separator()
                self.video_menu.add_command(label="查看详情", command=self.show_video_details)
            
            def create_user_data_tab(self):
                """创建用户数据查看标签页"""
                user_frame = ttk.Frame(self.notebook)
                self.notebook.add(user_frame, text='用户数据')
                
                # 主容器
                container = ttk.Frame(user_frame)
                container.pack(fill='both', expand=True, padx=10, pady=10)
                
                # 工具栏
                toolbar = ttk.Frame(container)
                toolbar.pack(fill='x', pady=5)
                
                # 添加导出按钮
                export_menu = tk.Menubutton(toolbar, text="导出数据", relief='raised')
                export_menu.pack(side='left', padx=5)
                
                export_menu.menu = tk.Menu(export_menu, tearoff=0)
                export_menu["menu"] = export_menu.menu
                export_menu.menu.add_command(label="导出Excel", command=self.export_user_excel)
                export_menu.menu.add_command(label="导出JSON", command=self.export_user_json)
                
                # 添加统计标签
                self.user_stats_label = ttk.Label(toolbar, text="共采集到 0 位用户")
                self.user_stats_label.pack(side='right', padx=5)
                
                # 创建表格
                columns = ('序号', '用户名', '抖音号', '获赞数', '粉丝数', '简介', '主页链接', '头像链接')
                self.user_tree = ttk.Treeview(container, columns=columns, show='headings', selectmode='extended')
                
                # 设置列标题和排序功能
                for col in columns:
                    self.user_tree.heading(col, text=col, command=lambda c=col: self.treeview_sort_column(self.user_tree, c, False))
                
                # 设置列宽
                self.user_tree.column('序号', width=50, anchor='center')
                self.user_tree.column('用户名', width=150)
                self.user_tree.column('抖音号', width=100)
                self.user_tree.column('获赞数', width=70, anchor='center')
                self.user_tree.column('粉丝数', width=70, anchor='center')
                self.user_tree.column('简介', width=200)
                self.user_tree.column('主页链接', width=150)
                self.user_tree.column('头像链接', width=150)
                
                # 添加滚动条
                scrollbar = ttk.Scrollbar(container, orient='vertical', command=self.user_tree.yview)
                self.user_tree.configure(yscrollcommand=scrollbar.set)
                
                # 布局
                self.user_tree.pack(side='left', fill='both', expand=True)
                scrollbar.pack(side='right', fill='y')
                
                # 绑定双击事件
                self.user_tree.bind('', self.on_user_tree_double_click)
                
                # 绑定右键菜单事件
                self.user_tree.bind('', self.show_user_context_menu)
                
                # 创建右键菜单
                self.user_menu = tk.Menu(self.root, tearoff=0)
                self.user_menu.add_command(label="复制主页链接", command=self.copy_user_link)
                self.user_menu.add_command(label="在浏览器中打开", command=self.open_user_in_browser)
                self.user_menu.add_separator()
                self.user_menu.add_command(label="查看详情", command=self.show_user_details)
            
            def create_analysis_tab(self):
                """创建数据分析标签页"""
                analysis_frame = ttk.Frame(self.notebook)
                self.notebook.add(analysis_frame, text='数据分析')
                
                # 主容器
                container = ttk.Frame(analysis_frame)
                container.pack(fill='both', expand=True, padx=10, pady=10)
                
                # 分析选项面板
                options_frame = ttk.LabelFrame(container, text='分析选项', padding=10)
                options_frame.pack(fill='x', padx=5, pady=5)
                
                # 分析按钮
                btn_frame = ttk.Frame(options_frame)
                btn_frame.pack(fill='x', pady=5)
                
                ttk.Button(btn_frame, text="互动数据分析", command=self.analyze_interaction_data).pack(side='left', padx=5, fill='x', expand=True)
                ttk.Button(btn_frame, text="内容长度分析", command=self.analyze_content_length).pack(side='left', padx=5, fill='x', expand=True)
                ttk.Button(btn_frame, text="高频词汇分析", command=self.analyze_keywords).pack(side='left', padx=5, fill='x', expand=True)
                
                # 图表类型选择
                chart_frame = ttk.Frame(options_frame)
                chart_frame.pack(fill='x', pady=5)
                
                ttk.Label(chart_frame, text="图表类型:").pack(side='left', padx=5)
                self.chart_type = tk.StringVar(value='bar')
                
                chart_types = [('柱状图', 'bar'), ('折线图', 'line'), ('饼图', 'pie')]
                for text, value in chart_types:
                    ttk.Radiobutton(
                        chart_frame,
                        text=text,
                        value=value,
                        variable=self.chart_type
                    ).pack(side='left', padx=5)
                
                # 分析结果区域
                result_frame = ttk.LabelFrame(container, text='分析结果', padding=10)
                result_frame.pack(fill='both', expand=True, padx=5, pady=5)
                
                # 创建分析结果文本框
                self.analysis_text = tk.Text(result_frame, wrap=tk.WORD, padx=10, pady=10)
                self.analysis_text.pack(fill='both', expand=True, pady=5)
                
                # 添加滚动条
                scrollbar = ttk.Scrollbar(result_frame, orient='vertical', command=self.analysis_text.yview)
                scrollbar.pack(side='right', fill='y')
                self.analysis_text.configure(yscrollcommand=scrollbar.set)
                
                # 结果操作按钮
                result_btn_frame = ttk.Frame(result_frame)
                result_btn_frame.pack(fill='x', pady=5)
                
                ttk.Button(result_btn_frame, text="清空分析结果", command=lambda: self.analysis_text.delete(1.0, tk.END)).pack(side='left', padx=5)
                ttk.Button(result_btn_frame, text="复制结果", command=self.copy_analysis_result).pack(side='left', padx=5)
                ttk.Button(result_btn_frame, text="保存结果", command=self.save_analysis_result).pack(side='left', padx=5)
            
            def create_help_tab(self):
                """创建帮助标签页"""
                help_frame = ttk.Frame(self.notebook)
                self.notebook.add(help_frame, text='使用帮助')
                
                # 主容器
                container = ttk.Frame(help_frame)
                container.pack(fill='both', expand=True, padx=10, pady=10)
                
                # 创建帮助文本框
                help_text = tk.Text(container, wrap=tk.WORD, padx=15, pady=15)
                help_text.pack(fill='both', expand=True)
                
                # 添加标签用于样式化文本
                help_text.tag_configure('title', font=('Microsoft YaHei', 14, 'bold'), foreground=self.primary_color)
                help_text.tag_configure('subtitle', font=('Microsoft YaHei', 12, 'bold'), foreground=self.secondary_color)
                help_text.tag_configure('highlight', foreground=self.highlight_color)
                
                # 添加滚动条
                scrollbar = ttk.Scrollbar(container, orient='vertical', command=help_text.yview)
                scrollbar.pack(side='right', fill='y')
                help_text.configure(yscrollcommand=scrollbar.set)
                
                # 帮助内容
                help_content = [
                    ("抖音作品分析工具使用指南\n", 'title'),
                    ("\n1. 数据采集\n", 'subtitle'),
                    ("支持两种采集方式:\n- 直接输入抖音链接\n- 关键词搜索采集\n\n", None),
                    ("关键词搜索支持以下类型:\n- 视频搜索\n- 用户搜索\n\n", None),
                    ("采集参数说明:\n- 滚动次数:决定采集数据量的多少\n- 延迟(秒):每次滚动的等待时间,建议2-3秒\n\n", None),
                    ("使用技巧:\n", 'highlight'),
                    ("- 采集时可随时点击停止采集\n- 建议设置适当的延迟避免被限制\n- 数据采集过程中请勿关闭浏览器窗口\n\n", None),
                    ("\n2. 数据查看\n", 'subtitle'),
                    ("视频数据:\n- 包含标题、作者、发布时间等信息\n- 双击可直接打开视频链接\n- 支持按列排序\n- 可导出为Excel或JSON格式\n\n", None),
                    ("用户数据:\n- 显示用户名、抖音号、粉丝数等信息\n- 双击可打开用户主页\n- 支持数据排序\n- 可单独导出用户数据\n\n", None),
                    ("\n3. 数据分析\n", 'subtitle'),
                    ("互动数据分析:\n- 统计总点赞数、平均点赞等指标\n- 展示互动数据分布情况\n\n", None),
                    ("内容长度分析:\n- 分析标题长度分布\n- 显示最长/最短标题统计\n\n", None),
                    ("高频词汇分析:\n- 提取标题中的关键词\n- 展示TOP100高频词汇\n- 计算词频占比\n\n", None),
                    ("\n4. 常见问题\n", 'subtitle'),
                    ("Q: 为什么采集速度较慢?\nA: 为了避免被反爬虫机制拦截,程序设置了延迟机制。\n\n", None),
                    ("Q: 如何提高采集成功率?\nA: 建议:\n- 设置适当的延迟时间(2-3秒)\n- 避免过于频繁的采集\n- 确保网络连接稳定\n\n", None),
                    ("Q: 数据导出格式说明?\nA: 支持两种格式:\n- Excel格式:适合数据分析和处理\n- JSON格式:适合数据备份和程序读取\n\n", None),
                    ("Q: 如何处理采集失败?\nA: 可以:\n- 检查网络连接\n- 增加延迟时间\n- 减少单次采集数量\n- 更换搜索关键词\n\n", None),
                    ("\n5. 注意事项\n", 'subtitle'),
                    ("合理使用:\n- 遵守抖音平台规则\n- 避免频繁、大量采集\n- 合理设置采集参数\n\n", None),
                    ("数据安全:\n- 及时导出重要数据\n- 定期备份采集结果\n\n", None),
                    ("使用建议:\n- 建议使用稳定的网络连接\n- 采集时避免其他浏览器操作\n- 定期清理浏览器缓存\n", None)
                ]
                
                # 插入帮助内容
                for text, tag in help_content:
                    if tag:
                        help_text.insert('end', text, tag)
                    else:
                        help_text.insert('end', text)
                
                help_text.config(state='disabled')  # 设置为只读
            
            # ====================== 以下是原有功能方法 ======================
            # 由于篇幅限制,这里只展示UI优化部分,原有功能方法保持不变
            # 请将原始代码中的功能方法复制到这里,保持完整功能
            
            def setup_logging(self):
                """设置日志"""
                log_dir = "logs"
                if not os.path.exists(log_dir):
                    os.makedirs(log_dir)
                    
                log_file = os.path.join(log_dir, f"douyin_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log")
                
                logging.basicConfig(
                    level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s',
                    handlers=[
                        logging.FileHandler(log_file, encoding='utf-8'),
                        logging.StreamHandler()
                    ]
                )
            
            def copy_preview_content(self):
                """复制预览内容到剪贴板"""
                content = self.preview_text.get(1.0, tk.END)
                if content.strip():
                    self.root.clipboard_clear()
                    self.root.clipboard_append(content)
                    messagebox.showinfo("成功", "预览内容已复制到剪贴板")
            
            def copy_analysis_result(self):
                """复制分析结果到剪贴板"""
                content = self.analysis_text.get(1.0, tk.END)
                if content.strip():
                    self.root.clipboard_clear()
                    self.root.clipboard_append(content)
                    messagebox.showinfo("成功", "分析结果已复制到剪贴板")
            
            def save_analysis_result(self):
                """保存分析结果到文件"""
                content = self.analysis_text.get(1.0, tk.END)
                if not content.strip():
                    messagebox.showwarning("警告", "没有可保存的分析结果!")
                    return
                
                filename = filedialog.asksaveasfilename(
                    defaultextension=".txt",
                    filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")],
                    initialfile=f"分析结果_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
                )
                
                if filename:
                    try:
                        with open(filename, 'w', encoding='utf-8') as f:
                            f.write(content)
                        messagebox.showinfo("成功", f"分析结果已保存到:\n{filename}")
                    except Exception as e:
                        messagebox.showerror("错误", f"保存文件失败: {str(e)}")
            
            def show_video_details(self):
                """显示视频详情"""
                selection = self.data_tree.selection()
                if not selection:
                    return
                
                item = selection[0]
                values = self.data_tree.item(item)['values']
                if not values:
                    return
                
                details = f"视频详情:\n\n标题: {values[1]}\n作者: {values[2]}\n发布时间: {values[3]}\n点赞数: {values[4]}\n链接: {values[5]}"
                messagebox.showinfo("视频详情", details)
            
            def show_user_details(self):
                """显示用户详情"""
                selection = self.user_tree.selection()
                if not selection:
                    return
                
                item = selection[0]
                values = self.user_tree.item(item)['values']
                if not values:
                    return
                
                details = f"用户详情:\n\n用户名: {values[1]}\n抖音号: {values[2]}\n获赞数: {values[3]}\n粉丝数: {values[4]}\n简介: {values[5]}\n主页链接: {values[6]}"
                messagebox.showinfo("用户详情", details)
            
            def show_user_context_menu(self, event):
                """显示用户右键菜单"""
                try:
                    item = self.user_tree.identify_row(event.y)
                    if not item:
                        return
                    
                    self.user_tree.selection_set(item)
                    self.user_menu.post(event.x_root, event.y_root)
                except Exception as e:
                    print(f"显示用户右键菜单错误: {str(e)}")
            
            def copy_user_link(self):
                """复制用户链接到剪贴板"""
                selection = self.user_tree.selection()
                if not selection:
                    return
                
                item = selection[0]
                values = self.user_tree.item(item)['values']
                if not values:
                    return
                
                user_url = values[6]
                if user_url:
                    self.root.clipboard_clear()
                    self.root.clipboard_append(user_url)
                    messagebox.showinfo("成功", "用户主页链接已复制到剪贴板")
            
            def open_user_in_browser(self):
                """在浏览器中打开用户主页"""
                selection = self.user_tree.selection()
                if not selection:
                    return
                
                item = selection[0]
                values = self.user_tree.item(item)['values']
                if not values:
                    return
                
                user_url = values[6]
                if user_url:
                    if not user_url.startswith('http'):
                        if user_url.startswith('//'):
                            user_url = 'https:' + user_url
                        else:
                            user_url = 'https://www.douyin.com' + user_url
                    
                    webbrowser.open(user_url)
            def on_tree_double_click(self, event):
                """处理表格双击事件"""
                try:
                    item = self.data_tree.selection()[0]
                    values = self.data_tree.item(item)['values']
                    if not values:
                        return
                         
                    video_url = values[5]  # 获取视频链接
                    if video_url:
                        # 确保URL格式正确
                        if not video_url.startswith('http'):
                            if video_url.startswith('//'):
                                video_url = 'https:' + video_url
                            elif video_url.startswith('/'):
                                video_url = 'https://www.douyin.com' + video_url
                            else:
                                video_url = 'https://www.douyin.com/' + video_url
                         
                        # 使用默认浏览器打开链接
                        import webbrowser
                        webbrowser.open(video_url)
                         
                except Exception as e:
                    print(f"打开视频链接错误: {str(e)}")
                    messagebox.showerror("错误", "无法打开视频链接")
         
            def on_user_tree_double_click(self, event):
                """处理用户表格双击事件"""
                try:
                    item = self.user_tree.selection()[0]
                    values = self.user_tree.item(item)['values']
                    if not values:
                        return
                     
                    user_url = values[6]  # 获取用户主页链接
                    if user_url:
                        # 确保URL格式正确
                        if not user_url.startswith('http'):
                            if user_url.startswith('//'):
                                user_url = 'https:' + user_url
                            elif user_url.startswith('/'):
                                user_url = 'https://www.douyin.com' + user_url
                            else:
                                user_url = 'https://www.douyin.com/' + user_url
                         
                        # 使用默认浏览器打开链接
                        import webbrowser
                        webbrowser.open(user_url)
                     
                except Exception as e:
                    print(f"打开用户主页链接错误: {str(e)}")
                    messagebox.showerror("错误", "无法打开用户主页链接")
         
            def create_analysis_tab(self):
                """创建数据分析标签页"""
                analysis_frame = ttk.Frame(self.notebook)
                self.notebook.add(analysis_frame, text='数据分析')
                 
                # 创建分析结果文本框
                self.analysis_text = tk.Text(analysis_frame, height=20, width=60)
                self.analysis_text.pack(pady=10, padx=10, fill='both', expand=True)
                 
                # 创建按钮框架
                button_frame = ttk.Frame(analysis_frame)
                button_frame.pack(pady=5)
                 
                # 添加分析按钮
                ttk.Button(button_frame, text="互动数据分析", command=self.analyze_interaction_data).pack(side='left', padx=5)
                ttk.Button(button_frame, text="内容长度分析", command=self.analyze_content_length).pack(side='left', padx=5)
                ttk.Button(button_frame, text="高频词汇分析", command=self.analyze_keywords).pack(side='left', padx=5)
                ttk.Button(button_frame, text="清空分析结果", command=lambda: self.analysis_text.delete(1.0, tk.END)).pack(side='left', padx=5)
             
            def start_search_collection(self):
                """开始搜索采集"""
                try:
                    # 验证输入
                    keyword = self.search_keyword.get().strip()
                    if not keyword:
                        messagebox.showwarning("警告", "请输入搜索关键词!")
                        return
                     
                    scroll_count = self.scroll_count.get().strip()
                    if not scroll_count.isdigit():
                        messagebox.showwarning("警告", "滚动次数必须是正整数!")
                        return
                     
                    delay = self.delay.get().strip()
                    try:
                        delay = float(delay)
                        if delay 
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码