admin
2025-03-31 4603536999de113969dd7164f3a04dcde9083480
初始化导入
4个文件已修改
5个文件已添加
581 ■■■■ 已修改文件
comment.py 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
comment_manager.py 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
comment_util.py 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.py 134 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
res/comment.txt 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
res/setting.conf 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
setting.py 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tool.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
video_manager.py 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
comment.py
@@ -1,4 +1,3 @@
import re
import threading
import time
@@ -9,7 +8,9 @@
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import comment_manager
import setting
from video_manager import VideoManger
class CommentManager:
@@ -50,20 +51,19 @@
        # 等到左侧菜单出现后才能执行后续操作
        wait = WebDriverWait(self.driver, 100)  # 最多等待10秒
        element = wait.until(EC.visibility_of_element_located((By.ID, "side-bar")))
        threading.Thread(target=lambda: self.click_like(self.driver), daemon=True).start()
        threading.Thread(target=lambda: self.process_videos(self.driver), daemon=True).start()
    def __process_like(self, comment_content, comment_element):
    def __process_like(self, video_name, video_date, comment_element):
        """
        处理单条评论的赞
        :param comment_content:
        :param comment_element:
        :return:
        """
        comment_pattern = re.compile(r'[\u4e00-\u9fa5]+')
        comment_content = re.sub("<img.*?>", "", comment_content)
        if not comment_pattern.search(comment_content):
            # 符合标准的评论
        user_name, comment_content, comment_time = self.__parse_comment_info(comment_element)
        if not comment_manager.is_need_click_like(video_name, video_date, user_name, comment_content):
            return
        comment_actions = comment_element.find_element(By.CLASS_NAME, "action-list").find_elements(By.CLASS_NAME,
                                                                                                   "action-item")
        classes: str = comment_actions[0].find_element(By.TAG_NAME, "svg").get_attribute("class")
@@ -72,50 +72,73 @@
            return
        like = comment_element.find_element(By.CLASS_NAME, "like-action")
        like.click()
        self.driver.implicitly_wait(2)
        # self.driver.implicitly_wait(2)
        time.sleep(2)
    def __process_reply(self, comment_content, comment_element):
    def __parse_comment_info(self, comment_element):
        """
        处理单条评论的回复
        :param comment_content:
        解析评论信息
        :param comment_element:
        :return:
        :return:(评论人,评论内容,评论时间)
        """
        user_name = comment_element.find_element(By.CLASS_NAME, "comment-user-name").get_attribute("innerHTML")
        comment_time = comment_element.find_element(By.CLASS_NAME, "comment-time").get_attribute("innerHTML")
        comment_content = comment_element.find_element(By.CLASS_NAME, "comment-content").get_attribute("innerHTML")
        return user_name, comment_content, comment_time
    def __parse_video_info(self, video_element):
        """
        解析视频信息
        :param comment_element:
        :return:(视频名称,视频时间,评论数量)
        """
        video_time = video_element.find_element(By.CLASS_NAME, "feed-time").get_attribute("innerHTML")
        comment_count = video_element.find_element(By.CLASS_NAME, "feed-comment-total").find_element(By.XPATH,
                                                                                                     "./span[2]").get_attribute(
            "innerHTML")
        video_name = video_element.find_element(By.CLASS_NAME, "comment-content").get_attribute("innerHTML")
        return video_name, video_time, comment_count
    def __process_reply(self, video_name, video_date, comment_element):
        """
        处理单条评论回复
        :param video_name:
        :param video_date:
        :param comment_element:
        :return: 是否需要点赞
        """
        def get_reply_comment(nick_name, content):
            if not setting.is_reply_comment():
                return None
            # 内容是否符合标准
            for t in self.comment_templates:
                if re.match(t[0], content):
                    # 满足内容
                    return t[1].replace("[昵称]", nick_name)
            return comment_manager.get_replay_content(video_name, video_date, nick_name, content)
        comment_pattern = re.compile(r'[\u4e00-\u9fa5]+')
        comment_content = re.sub("<img.*?>", "", comment_content)
        if not comment_pattern.search(comment_content):
            # 符合标准的评论
            return
        comment_user_name, comment_content, comment_time = self.__parse_comment_info(comment_element)
        try:
            comment_reply_list = comment_element.find_element(By.CLASS_NAME, "comment-reply-list")
            if comment_reply_list.find_element(By.XPATH, ".//div[normalize-space()='作者']"):
                print("已经回复。。。。")
                return
                return False
        except:
            print("还没回复。。。。")
        replay_content = get_reply_comment(comment_user_name, comment_element)
        if not replay_content:
            # 不需要评论
            print("不需要回复。。。。")
            return True
        # 需要回复
        comment_actions = comment_element.find_element(By.CLASS_NAME, "action-list").find_elements(By.CLASS_NAME,
                                                                                                   "action-item")
        # 点击评论
        comment_actions[1].click()
        wait = WebDriverWait(self.driver, 5)  # 最多等待10秒
        element = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "comment-create-content")))
        # TODO 昵称
        replay_content = get_reply_comment("昵称", comment_element)
        if not replay_content:
            # 不需要评论
            return
        wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "comment-create-content")))
        time.sleep(1)
        self.driver.find_element(By.CLASS_NAME,
                                 "comment-create-content").find_element(By.TAG_NAME,
                                                                        "textarea").send_keys(replay_content)
@@ -123,8 +146,16 @@
        self.driver.find_element(By.CLASS_NAME,
                                 "comment-create-content").find_element(By.XPATH, "div[3]/div[2]").click()
        time.sleep(2)
        return False
    def __click_like_all(self, driver, start_index=0):
    def __process_comments(self, driver, start_index=0, video_info=None):
        """
        :param driver:
        :param start_index:
        :param video_info:(视频内容, 视频日期, 评论次数)
        :return:
        """
        scroll_list = driver.find_element(By.CLASS_NAME, "feed-comment__wrp")
        loadmore = scroll_list.find_element(By.CLASS_NAME, "loadmore__dot")
@@ -137,34 +168,60 @@
        for index in range(start_index, len(comments)):
            comment = comments[index]
            # 评论内容
            comment_content = comment.find_element(By.CLASS_NAME, "comment-content").get_attribute("innerHTML")
            user_name, comment_content, comment_time = self.__parse_comment_info(comment)
            if not comment_content:
                continue
            print("=======评论内容:", comment_content)
            self.__process_reply(comment_content, comment)
            self.__process_like(comment_content, comment)
            need_like = self.__process_reply(video_info[0], video_info[1], comment)
            if need_like:
                print("需要点赞")
                self.__process_like(video_info[0], video_info[1], comment)
            else:
                print("不需要点赞")
        # 往下滑动
        if has_more:
            driver.execute_script(
                "var __comment_scroll = document.getElementsByClassName('feed-comment__wrp')[0]; __comment_scroll.scrollTop = __comment_scroll.scrollHeight;")
            print("往下滚动")
            time.sleep(3)
            self.__click_like_all(driver, start_index=len(comments))
            self.__process_comments(driver, start_index=len(comments))
        else:
            print("没有更多了")
            print("没有更多评论了")
    def click_like(self, driver: webdriver.Chrome):
    def process_videos(self, driver: webdriver.Chrome, start_index=0):
        wait = WebDriverWait(driver, 100)  # 最多等待10秒
        element = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "feeds-container")))
        scroll_list = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "feeds-container")))
        time.sleep(1)
        # 查找视频列表
        videos_root = driver.find_element(By.CLASS_NAME, "feeds-container")
        videos = videos_root.find_elements(By.CLASS_NAME, "comment-feed-wrap")
        for video in videos:
        for i in range(start_index, len(videos)):
            # 选择视频
            video = videos[i]
            # 解析视频内容
            video_name, video_time, comment_count = self.__parse_video_info(video)
            # 判断是否要点击进去
            if not VideoManger().is_need_click(video_name, video_time, comment_count):
                continue
            video.click()
            driver.implicitly_wait(2)
            self.__click_like_all(driver)
            self.__process_comments(driver, video_info=(video_name, video_time, comment_count))
            # 5s处理一个视频
            time.sleep(5)
        loadmore = scroll_list.find_element(By.CLASS_NAME, "loadmore__dot")
        # 获取父控件
        loadmore = loadmore.find_element(By.XPATH, "./..")
        has_more = loadmore.value_of_css_property("display") == "none"
        if has_more:
            driver.execute_script(
                "var __video_scroll = document.getElementsByClassName('feeds-container')[0]; __video_scroll.scrollTop = __video_scroll.scrollHeight;")
            print("往下滚动")
            time.sleep(3)
            self.process_videos(driver, start_index=len(videos))
        else:
            print("没有更多视频了")
            VideoManger().add_video_infos([self.__parse_video_info(v) for v in videos])
    def close(self):
        if self.driver:
comment_manager.py
New file
@@ -0,0 +1,81 @@
"""
评论管理
"""
# 保存回复视频评论的用户昵称
# {"视频名称+发布日期":{"评论用户的昵称":{"评论内容集合"}}}
import comment_util
__reply_video_comment_user_name_dict = {}
def add_reply_record(video_name, video_date, comment_nick_name, comment_content):
    """
    添加评论内容
    :param video_name:
    :param video_date:
    :param comment_nick_name:
    :return:
    """
    k = f"{video_name}{video_date}"
    if k not in __reply_video_comment_user_name_dict:
        __reply_video_comment_user_name_dict[k] = {}
    if comment_nick_name not in __reply_video_comment_user_name_dict[k]:
        __reply_video_comment_user_name_dict[k][comment_nick_name] = set()
    __reply_video_comment_user_name_dict[k][comment_nick_name].add(comment_content)
def get_replay_content(video_name, video_date, comment_nick_name, comment_content):
    """
    获取回复内容
    :param video_name:视频名称
    :param video_date:视频日期
    :param comment_nick_name:评论昵称
    :param comment_content:评论内容
    :return:
    """
    k = f"{video_name}{video_date}"
    if k not in __reply_video_comment_user_name_dict:
        __reply_video_comment_user_name_dict[k] = {}
    if __reply_video_comment_user_name_dict[k].get(comment_nick_name):
        # 评论过了就不评论了
        return None
    # 获取评论的正则表达式
    comment_templates = comment_util.get_comment_templates()
    if not comment_templates:
        return None
    if not comment_content:
        return None
    # 替换评论内容中的img
    comment_content = comment_util.replace_img_with_alt(comment_content)
    for r in comment_templates:
        if r.match(r[0], comment_content):
            # 能够匹配到正则表达式
            result = comment_util.load_content(r[1], comment_nick_name, comment_content)
            if result:
                return result
    return None
def is_need_click_like(video_name, video_date, comment_nick_name, comment_content):
    """
    是否需要点赞
    :param video_name:
    :param video_date:
    :param comment_nick_name:
    :param comment_content:
    :return:
    """
    like_conditions = comment_util.get_like_conditions()
    if not like_conditions:
        return False
    # 替换评论内容中的img
    comment_content = comment_util.replace_img_with_alt(comment_content)
    for r in like_conditions:
        if r.match(r, comment_content):
            # 能够匹配到正则表达式
            return True
    return False
comment_util.py
New file
@@ -0,0 +1,125 @@
import os
import random
import re
import setting
def replace_img_with_alt(html_text):
    """
    将HTML中的所有<img>标签替换为其alt属性内容
    如果没有alt属性,则替换为空字符串或指定默认值
    """
    pattern = r'<img\b[^>]*\balt=(["\'])(.*?)\1[^>]*>|<img\b[^>]*>'
    def replacement(match):
        if match.group(2):  # 如果匹配到alt属性
            return match.group(2)  # 返回alt属性内容
        return ''  # 没有alt属性则替换为空
    return re.sub(pattern, replacement, html_text, flags=re.IGNORECASE).strip()
def get_like_conditions():
    """
    获取点赞的条件
    :return:[正则表达式,...]
    """
    condition_str = setting.get_like_conditions()
    return [x.split("#")[0] for x in condition_str.split("\n") if x]
def get_comment_templates():
    """
    获取评论模版
    :return:[(匹配的正则, 评论的内容)]
    """
    condition_str = setting.get_comment_templates()
    return [(x.split("#")[0], x.split("#")[1]) for x in condition_str.split("\n") if x]
def __get_common_emojis():
    comment_emojis = setting.get_common_emojis()
    if comment_emojis:
        return re.findall("\[.*?\]", comment_emojis)
    return []
def __load_content(content_template, nick_name, comment_content):
    """
    加载内容
    :param content_template:
    :param nick_name:
    :param comment_content:
    :return:
    """
    # 替换表情
    pattern = r'【([\d-]+)】'
    def replacement_emojis(match):
        match_str = match.group(1)
        if match_str:
            start = 0
            end = 0
            if match_str.find("-") >= 0:
                sts = match_str.split("-")
                if sts[0]:
                    start = int(sts[0])
                if sts[1]:
                    end = int(sts[1])
            else:
                start = int(match_str)
                end = int(match_str)
            if start == 0 and end == 0:
                return ""
            count = random.randint(start, end)
            result_str = ""
            common_emojis = __get_common_emojis()
            for i in range(count):
                result_str += common_emojis[random.randint(0, len(common_emojis) - 1)]
            return result_str  # 返回alt属性内容
        return ''  # 没有alt属性则替换为空
    result = re.sub(pattern, replacement_emojis, content_template, flags=re.IGNORECASE).strip()
    comment_emojis = re.findall(r"\[.*?\]", comment_content)
    last_emoji = ""
    if comment_emojis:
        last_emoji = comment_emojis[-1]
    # 替换昵称与原内容
    result = result.replace("【昵称】", nick_name).replace("【内容】", comment_content).replace("【最后一个表情】", last_emoji)
    # 替换最后一个表情
    return result
def load_content(content_template, nick_name, comment_content):
    """
    加载内容
    :param content_template:
    :param nick_name:
    :param comment_content:
    :return:
    """
    # 替换表情
    pattern = r'\{(.*?)\}'
    def replacement_express(match):
        match_str = match.group(1)
        if match_str:
            # 替换或者表达式
            if match_str.find("|") >= 0:
                sts = match_str.split("|")
                return sts[random.randint(0, len(sts)-1)]
            return match_str
        return ''
    result = re.sub(pattern, replacement_express, content_template, flags=re.IGNORECASE).strip()
    # 替换最后一个表情
    return __load_content(result, nick_name, comment_content)
if __name__ == "__main__":
    print(os.getcwd())
    st = "{是的,你的观点很赞|好吧[爱心]|谢谢[抱拳]|是的[强]|确实可能有些不对[裂开]}"
    comment_emojis = load_content(st,"昵称","评论内容本身")
    print(comment_emojis)
main.py
@@ -1,9 +1,11 @@
import re
import threading
import wx
import setting
from comment import CommentManager
def show_warning(content, click=None):
    toastone = wx.MessageDialog(None, content, "提示", wx.YES_DEFAULT | wx.ICON_WARNING)
@@ -18,6 +20,7 @@
    if toastone.ShowModal() == wx.ID_YES:  # 如果点击了提示框的确定按钮
        click()
        toastone.Destroy()
class MainFrame(wx.Frame):
    def __bind_event(self):
@@ -69,7 +72,10 @@
            setting.set_chromedriver_path(chromedriver_path)
            setting.set_comment_templates(comment_templates)
            setting.set_reply_comment(comment)
            setting.set_common_emojis(self.text_emojis.GetValue())
            setting.set_like_conditions(self.text_like_conditions.GetValue())
            show_info("保存成功")
        self.Bind(wx.EVT_CLOSE, self.OnFrameClose)
        self.btn_start_comment.Bind(wx.EVT_BUTTON, start_comment)
        self.btn_chrome_path.Bind(wx.EVT_BUTTON, on_select_chrome_file)
@@ -77,69 +83,155 @@
        self.btn_save.Bind(wx.EVT_BUTTON, on_save)
    def __init(self):
        self.comment_manager = None
        self.cb_like.SetValue(setting.is_click_like())
        self.cb_comment.SetValue(setting.is_reply_comment())
        self.text_comments.SetValue(setting.get_comment_templates())
        self.text_chrome_path.SetValue(setting.get_chrome_path())
        self.text_chromedriver_path.SetValue(setting.get_chromedriver_path())
        self.text_emojis.SetValue(setting.get_common_emojis())
        self.text_like_conditions.SetValue(setting.get_like_conditions())
    def __init__(self):
    def __create_setting_view(self, panel):
        def create_label(text):
            return wx.StaticText(self, wx.ID_ANY, text, size=wx.Size(150, -1), style=wx.ALIGN_RIGHT)
            return wx.StaticText(panel, wx.ID_ANY, text, size=wx.Size(150, -1), style=wx.ALIGN_RIGHT)
        wx.Frame.__init__(self, None, -1, "视频号助手",
                          size=(600, 500))
        self.SetBackgroundColour(wx.Colour(224, 224, 224))
        boxsier = wx.BoxSizer(wx.VERTICAL)
        # 浏览器地址
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("Chrome浏览器路径:"), 0, wx.ALIGN_CENTER_VERTICAL)
        self.text_chrome_path = wx.TextCtrl(self, wx.ID_ANY, size=wx.Size(-1, -1))
        self.text_chrome_path = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, -1))
        ss.Add(self.text_chrome_path, 1, wx.RIGHT, 10)
        self.btn_chrome_path = wx.Button(self, wx.ID_ANY, "选择文件")
        self.btn_chrome_path = wx.Button(panel, wx.ID_ANY, "选择文件")
        ss.Add(self.btn_chrome_path, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        # 浏览器驱动地址
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("Chrome浏览器驱动路径:"), 0, wx.ALIGN_CENTER_VERTICAL)
        self.text_chromedriver_path = wx.TextCtrl(self, wx.ID_ANY, size=wx.Size(-1, -1))
        self.text_chromedriver_path = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, -1))
        ss.Add(self.text_chromedriver_path, 1, wx.RIGHT, 10)
        self.btn_chromedriver_path = wx.Button(self, wx.ID_ANY, "选择文件")
        self.btn_chromedriver_path = wx.Button(panel, wx.ID_ANY, "选择文件")
        ss.Add(self.btn_chromedriver_path, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        # 是否点赞
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("是否点赞:"), 0, wx.ALIGN_CENTER_VERTICAL)
        self.cb_like = wx.CheckBox(self, wx.ID_ANY, "")
        self.cb_like = wx.CheckBox(panel, wx.ID_ANY, "")
        ss.Add(self.cb_like, 0, wx.ALIGN_CENTER_VERTICAL)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        # 是否评论
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("是否评论:"), 0, wx.ALIGN_CENTER_VERTICAL)
        self.cb_comment = wx.CheckBox(self, wx.ID_ANY, "")
        self.cb_comment = wx.CheckBox(panel, wx.ID_ANY, "")
        ss.Add(self.cb_comment, 0, wx.ALIGN_CENTER_VERTICAL)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        # 常用表情
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("常用表情:"), 0)
        self.text_emojis = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, 50), style=wx.TE_MULTILINE)
        ss.Add(self.text_emojis, 1, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        # 评论内容
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("评论模版:"), 0)
        self.text_comments = wx.TextCtrl(self, wx.ID_ANY, size=wx.Size(-1, 150), style=wx.TE_MULTILINE)
        self.text_comments = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, 150), style=wx.TE_MULTILINE)
        ss.Add(self.text_comments, 1, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        boxsier.Add(wx.StaticText(self, wx.ID_ANY, "模版与内容之间采用#分隔,如: 谢谢$#[昵称]不客气\n变量:[昵称]\n备注:$-结尾  ^-开始"), 0, wx.LEFT,
        boxsier.Add(wx.StaticText(panel, wx.ID_ANY, "模版与内容之间采用#分隔,如: 谢谢$#[昵称]不客气\n变量:【昵称】,【内容】,【最后一个表情】,【1-3】\n备注:$-结尾  ^-开始"), 0, wx.LEFT,
                    150)
        self.btn_save = wx.Button(self, wx.ID_ANY, "保存")
        boxsier.Add(create_label(""))
        boxsier.Add(self.btn_save, 0, wx.LEFT, 150)
        # 点赞条件
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("点赞条件:"), 0)
        self.text_like_conditions = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, 80), style=wx.TE_MULTILINE)
        ss.Add(self.text_like_conditions, 1, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        self.btn_start_comment = wx.Button(self, wx.ID_ANY, "开始")
        boxsier.Add(self.btn_start_comment)
        self.SetSizer(boxsier)
        ss = wx.BoxSizer(wx.HORIZONTAL)
        self.btn_save = wx.Button(panel, wx.ID_ANY, "保存")
        ss.Add(self.btn_save, 0, wx.LEFT, 150)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        panel.SetSizer(boxsier)
    def __create_test_view(self, panel):
        def create_label(text):
            return wx.StaticText(panel, wx.ID_ANY, text, size=wx.Size(80, -1), style=wx.ALIGN_RIGHT)
        def on_excute(evt):
            # pattern =  self.test_regex.GetValue().encode('unicode_escape').decode("utf-8")
            pattern = self.test_regex.GetValue()
            regex = re.compile(pattern)
            content = self.test_text.GetValue()
            result = regex.match(content)
            result_list=[]
            if result:
                result_list.append("是否匹配:匹配")
            else:
                result_list.append("是否匹配:不匹配")
            result = regex.findall(content)
            result_list.append("匹配内容:" + ",".join(result))
            self.test_result.SetValue("\n".join(result_list))
        boxsier = wx.BoxSizer(wx.VERTICAL)
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("正则表达式:"), 0, wx.ALIGN_CENTER_VERTICAL)
        self.test_regex = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, -1))
        ss.Add(self.test_regex, 1, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("内容:"), 0)
        self.test_text = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, 100),style=wx.TE_MULTILINE)
        ss.Add(self.test_text, 1, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label("结果:"), 0)
        self.test_result = wx.TextCtrl(panel, wx.ID_ANY, size=wx.Size(-1, 100), style=wx.TE_READONLY|wx.TE_MULTILINE)
        ss.Add(self.test_result, 1, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        ss = wx.BoxSizer(wx.HORIZONTAL)
        ss.Add(create_label(""), 0, wx.ALIGN_CENTER_VERTICAL)
        self.test_excute = wx.Button(panel, wx.ID_ANY, "执行测试")
        ss.Add(self.test_excute, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
        boxsier.Add(ss, 0, wx.EXPAND | wx.TOP, 10)
        self.test_excute.Bind(wx.EVT_BUTTON, on_excute)
        panel.SetSizer(boxsier)
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "视频号助手",
                          size=(900, 600))
        self.SetBackgroundColour(wx.Colour(224, 224, 224))
        root_sizer = wx.FlexGridSizer(2, 2, 10, 10)
        # ------设置页面------
        panel_setting = wx.Panel(self, wx.ID_ANY, size=wx.Size(500, -1))
        self.__create_setting_view(panel_setting)
        root_sizer.Add(panel_setting)
        # ------测试界面------
        panel_test = wx.Panel(self, wx.ID_ANY, size=wx.Size(300, 400))
        self.__create_test_view(panel_test)
        root_sizer.Add(panel_test)
        # ------执行页面------
        panel_action = wx.Panel(self, wx.ID_ANY, size=wx.Size(500, 100))
        self.btn_start_comment = wx.Button(panel_action, wx.ID_ANY, "开始")
        root_sizer.Add(panel_action)
        self.SetSizer(root_sizer)
        self.__init()
        self.__bind_event()
res/comment.txt
New file
@@ -0,0 +1,4 @@
.*不对.*#{是的,你的观点很赞|好吧[爱心]|谢谢[抱拳]|是的[强]|确实可能有些不对[裂开]}
.*对.*|.*支持.*|.*没毛病.*|.*一样.*|.*没错.*|.*有道理.*#{感谢你的认同|感谢你的评价|谢谢你的认同|感恩你的认同|谢谢你的评论|感恩你的认可|是的,你说的没错|你的认同我很感激}{【1-3】}
.*太少了.*#{是的,确实不多}{【1-3】}
res/setting.conf
@@ -1,7 +1,12 @@
[config]
comment_templates = 测试234234你好234234
comment_templates = [*]$#[*]
    不对#
    对#
    ^你#123123
reply_comment = 1
click_like = 1
chromedriver_path = D:\workspace\python\wechat_helper\chromedriver.exe
chrome_path = D:\workspace\python\wechat_helper\chromedriver.exe
common_emojis = [爱心] [合十] [拥抱] [抱拳] [强] [玫瑰] [胜利] [666] [呲牙] [愉快]
like_conditions = [\u4e00-\u9fa5]{2,}#最少2个字中文
setting.py
@@ -102,5 +102,38 @@
    return cp.get("config", "comment_templates")
# -------------------------------常用表情--------------------------
def set_common_emojis(content):
    # 设置是否置顶
    cp = __read_setting()
    cp.set("config", "common_emojis", content)
    __write_setting(cp)
# 获取是否置顶
def get_common_emojis():
    try:
        cp = __read_setting()
        return cp.get("config", "common_emojis")
    except:
        return ""
# -------------------------------点赞条件--------------------------
def set_like_conditions(content):
    # 设置是否置顶
    cp = __read_setting()
    cp.set("config", "like_conditions", content)
    __write_setting(cp)
# 获取是否置顶
def get_like_conditions():
    try:
        cp = __read_setting()
        return cp.get("config", "like_conditions")
    except:
        return ""
if __name__ == "__main__":
    pass
tool.py
New file
@@ -0,0 +1,15 @@
def singleton(cls):
    """
    单例装饰器
    @param cls:
    @return:
    """
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance
video_manager.py
New file
@@ -0,0 +1,47 @@
import os
import time
import tool
@tool.singleton
class VideoManger:
    __video_cache_path = "datas/videos.json"
    # {"视频内容+视频时间":(评论数量,更新时间)}
    __video_data_cache_dict = {}
    def __init__(self):
        if os.path.exists(self.__video_cache_path):
            with open(self.__video_cache_path, encoding="utf-8", mode='r') as f:
                lines = f.readlines()
                if lines:
                    self.__video_data_cache_dict = eval(lines[0])
    def is_need_click(self, video_name, video_time, comment_count):
        """
        是否需要点击
        :param video_name: 视频名称
        :param video_time: 视频时间
        :param comment_count: 评论数量
        :return:
        """
        k = f"{video_name}{video_time}"
        if k not in self.__video_data_cache_dict:
            return True
        if comment_count - self.__video_data_cache_dict[k][0] > 0:
            return True
        return False
    def add_video_infos(self, video_infos):
        """
        添加视频信息
        :param video_infos:
        :return:
        """
        print("保存所有视频内容")
        self.__video_data_cache_dict = {f"{x[0]}{x[1]}": (x[2], time.time()) for x in video_infos}
        # 保存到文件
        with open(self.__video_cache_path, encoding="utf-8", mode='w') as f:
            f.write(f"{self.__video_data_cache_dict}")