用python写的一个可以多轮对话的聊天助手或机器人,也可以用来查询和下载全网音乐(2)

第二篇。

因为考虑到有一些人不会用数据库,所以这篇文章用了最简单的csv来存放聊天数据

这个又增加了一些的功能。

这次搞了一个yaml的配置文件用来存放路径

一行一行看看这些路径下放了什么

如图:

那个模型是我用yolov5训练出来的一个识别人脸模型,最后我会把模型放出来的 。第一行数据库那个不用管,我们只需要把第二行及以下的路径改成自己的就行了

这个是csv里面的内容。

 日志:

日志文件不会自己生产,需要自己去创建,最后把路径改成自己的就好

还有个微信自动登陆的 ,有兴趣的可以玩玩,就是一个简单的识别图片然后单击和图片内容一样的东西

 这个就是微信的下载路径

 

 人脸识别模型下载地址:

 链接:https://pan.baidu.com/s/13v9s7jyrb9MgWnQdpsOf7g?pwd=gj5s 
提取码:gj5s

阿里网盘不给分享,只能百度了

创建一个config.yaml文件,里面的内容为,记得改路径啊

#对话内容路径'csv的'
csv: D:\pycharm\PY_wenjian\hf.csv
#下载路径
yinye: E:\视屏剪辑\yinyue
# 音乐播放路径
bfyinye: E:\视屏剪辑\yinyue
#识别图片路径
wei_tu: D:\pycharm\wulianwang\tupian\weixin.png
#微信下载路径
weixin: D:\weixin\WeChat\WeChat.exe
# 模型路径
moxing: C:/Users/lenovo/Downloads/yolov5/runs/train/exp2/weights/best.pt
# 定义日志文件路径
rz: D:\pycharm\wulianwang\rzwj\file.txt

创建config.yaml文件后,要在源代码加上路径,就是配置文件1那里,还有一个配置文件2

 

 有一些库你们可能要自己安装:pip install 库名

我上一篇文章也有讲

import pandas as pd
import random
import time
import requests
import jsonpath
import os
import cv2
import win32api as api
import  pyautogui as gui
import torch
import os
import difflib
import webbrowser
from yolov5 import YOLOv5
import yaml
# 记录开始时间
start_time = time.time()
# 打开配置文件1
with open('D:\pycharm\wulianwang\config.yaml', encoding='utf-8') as f:
    config = yaml.safe_load(f)
# 定义日志文件路径
LOG_FILE_PATH = config['rz']

# 打开日志文件
with open(LOG_FILE_PATH, 'a') as log_file:
    # 记录程序开始时间
    start_time = time.time()
    start_localtime = time.localtime(start_time)
    start_strftime = time.strftime('%Y-%m-%d %H:%M:%S', start_localtime)

    # 写入程序开始时间到日志文件
    end_time = time.time()
    end_localtime = time.localtime(end_time)
    end_strftime = time.strftime('%Y-%m-%d %H:%M:%S', end_localtime)
    log_file.write(f'[{start_strftime}] 程序开始时间:{end_strftime}\n')
    开始时间 = end_strftime

    # 打开配置文件2
    with open('D:\pycharm\wulianwang\config.yaml', encoding='utf-8') as f:
        config = yaml.safe_load(f)
    # 以下是程序的主要逻辑,可以根据需求修改
    try:
        # 连接对话内容
        data = pd.read_csv(config['csv'], encoding='gbk')# 配置文件yaml的内容,读取CSV文件,指定编码格式为utf-8
        #data = pd.read_csv('your_dataset.csv', encoding='utf-8')
        log_file.write(f'[{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}] "成功连接csv"\n')
    except Exception as e:
        log_file.write(f'[{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}] 连接csv发生错误: {e}\n')


    try:

        # 获取问题和答案列表
        questions = data['问题'].tolist()
        answers = data['答案'].tolist()

        log_file.write(f'[{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}] "成功读取列表"\n')

    except Exception as e:
        log_file.write(f'[{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}] 读取列表发生错误: {e}\n')

    # 定义匹配度通过关键词计数的函数

    def get_match_score(user_input, question):
        score = 0
        if question is None:
            return score
        words = question.split()
        for word in user_input.split():
            if word in words:
                score += 1
        return score

    # 定义音乐模块
    def song_download(url, title, author, path):
        os.makedirs(path, exist_ok=True)
        mp3_path = os.path.join(path, f"{title}-{author}.mp3")
        print('歌曲:{0}-{1},正在下载...'.format(title, author))
        content = requests.get(url).content
        with open(file=mp3_path, mode='wb') as f:
            f.write(content)
        print('下载完毕,{0}-{1},请试听'.format(title, author))
    # 欢迎信息
    print("欢迎!输入'退出'结束对话。")
    # 对话循环
    while True:
        # 获取用户输入的问题
        user_input = input("您: ")
        # 判断是否退出对话
        if user_input.lower() == '退出':
            print("再见!")
            time.sleep(1)
            print("---程序结束---")
            break
        elif user_input.strip() == '':  # .strip()用于去除字符串两端的空白字符(包括空格、制表符和换行符
            print("陈文茜:好歹写点字吧!")
            continue  # 用于跳过当前(while)循环中剩余的代码,并继续下一次循环的执行

        # 判断是否下载音乐
        elif user_input.lower()[0:4] == '下载音乐':
            if user_input.lower()[0:4] == '下载音乐':  # 如果输入的字符的前两位为下载则进入音乐下载循环
                print("正在加载...")
                time.sleep(0.5)  # 延迟0.5秒
                while user_input.lower()[0:4] == '下载音乐':  # 如果输入的字符的前两位为下载则进入音乐下载循环
                    name = input("请输入歌曲名称:(输入y退出)")
                    name = name.lower()  # .lower() 用于将字符串中的所有字符转换为小写字母。
                    if name == "y":
                        break
                    elif name.strip() == "":
                        print("输入的歌曲名称无效,请重新输入")
                        continue


                    def get_music_name():
                        # global nama
                        # name = nama
                        print("1.网易云:netease\n2.QQ:qq\n3.酷狗:kugou\n4.酷我:kuwo\n5.百度:baidu\n6.喜马拉雅:ximalaya")
                        xuhao_dict = {}
                        xuhao_dict[1] = "netease"
                        xuhao_dict[2] = "qq"
                        xuhao_dict[3] = "kugou"
                        xuhao_dict[4] = "kuwo"
                        xuhao_dict[5] = "baidu"
                        xuhao_dict[6] = "ximalaya"

                        # 下面这个定义修复了输入不是数字会报错的问题
                        def get_clbc2():
                            while True:

                                num = input("输入音乐平台类型序号:")
                                if num.isnumeric():# isnumeric判断字符串是否只包含数字字符
                                    return int(num)
                                else:
                                    time.sleep(0.5)
                                    print('人家输入的是歌曲的版本序号,你个傻狗!!!')
                                    print('')
                                    time.sleep(0.5)
                                    print('请重新输入歌曲的版本序号')
                                    print('')

                        num = get_clbc2()

                        print('正在搜索....')
                        platform = xuhao_dict[num]
                        print("-------------------------------------------------------")
                        url = 'https://music.liuzhijin.cn/'
                        headers = {
                            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36",
                            "x-requested-with": "XMLHttpRequest",
                        }
                        param = {
                            "input": name,
                            "filter": "name",
                            "type": platform,
                            "page": 1,
                        }
                        res = requests.post(url=url, data=param, headers=headers)
                        json_text = res.json()

                        titles = jsonpath.jsonpath(json_text, '$..title')
                        authors = jsonpath.jsonpath(json_text, '$..author')
                        urls = jsonpath.jsonpath(json_text, '$..url')

                        if titles:
                            songs = list(zip(titles, authors, urls))
                            for index, song in enumerate(songs):
                                print(f"{index + 1}. {song[0]} - {song[1]}")
                            print("-------------------------------------------------------")

                            # 下面这个定义修复了输入不是数字会报错的问题
                            def get_clbc2():
                                while True:
                                    chosen_index = input("请输入您想下载的歌曲版本:")

                                    if chosen_index.isnumeric(): # 判断字符串是否只包含数字字符
                                        return int(chosen_index)
                                    else:
                                        print("")
                                        print('请重新输入歌曲序号!!!')
                                        print('')

                            chosen_index = get_clbc2()  # 将函数赋值给chosen_index
                            chosen_index = chosen_index - 1  # 使下载的歌曲版本的索引从1开始
                            if chosen_index >= 0 and chosen_index < len(songs):
                                # download_path = input("请输入下载路径:")

                                download_path = config['yinye']  # 下载路径,在yaml可修改

                                print('当前下载路径:', download_path)
                                song_download(songs[chosen_index][2], songs[chosen_index][0], songs[chosen_index][1],download_path)
                        else:
                            print("对不起,暂无搜索结果!")


                    get_music_name()
                    pass
            else:
                pass

        if user_input[0:4] == '下载音乐':  # 这里是重新开始对话循环
            continue
    #-------------------------------------------------------------------------------
        if user_input[-3:] == '摄像头':
            # 打开摄像头
            print("正在开启...")

            cap = cv2.VideoCapture(0)
            cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
            cv2.resizeWindow('frame', 640, 480)
            zxyc = True  # 标志变量
            while True:
                # 读取一帧图像
                ret, frame = cap.read()
                if not ret:
                    break
                # 显示图像
                frame = cv2.resize(frame, (640, 480))  # 随着窗口放大而放大
                cv2.imshow('frame', frame)
                if zxyc:
                    zxyc = "按'q'键退出循环"
                    print(zxyc)  # 执行只需要执行一次的语句
                    zxyc = False  # 将标志变量设为 False,确保下次循环不再执行

                # 按'q'键退出循环
                if cv2.waitKey(1) & 0xFF == ord('q'):

                    break
            # 释放摄像头并关闭所有窗口
            cap.release()
            cv2.destroyAllWindows()
            continue
#----------------------------------------------------------------------
        if user_input[-4:] == '人脸识别':

            # 加载模型
            model = torch.hub.load('ultralytics/yolov5', 'custom',path=config['moxing'])

            # 打开摄像头
            cap = cv2.VideoCapture(0)
            cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
            cv2.resizeWindow('frame', 640, 480)
            zxyc = True  # 标志变量
            while True:
                # 读取一帧图像
                ret, frame = cap.read()
                if not ret:
                    break

                # 使用模型进行预测
                results = model(frame)

                # 在屏幕上显示预测结果
                for result in results.xyxy[0]:
                    x1, y1, x2, y2, conf, cls = result
                    cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
                    cv2.putText(frame, str(cls), (int(x1), int(y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

                # 显示图像
                frame = cv2.resize(frame, (640, 480))
                cv2.imshow('frame', frame)
                if zxyc:
                    zxyc = "按'q'键退出循环"
                    print(zxyc)  # 执行只需要执行一次的语句
                    end_time = time.time()
                    # 计算运行时间
                    zxyc = elapsed_time = end_time - start_time
                    print("人脸识别代码运行时间:", zxyc, "秒")
                    zxyc = False  # 将标志变量设为 False,确保下次循环不再执行
                # 按'q'键退出循环
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    # tc = input('按q键退出循环')
                    # tc = tc.lower()
                    # if tc == 'q':
                    break
            # 释放摄像头并关闭所有窗口
            cap.release()
            cv2.destroyAllWindows()
            continue
 # ----------------------------------------------------------------------



        if user_input == '打开微信':
            weixin = config['weixin']#微信路径
            api.ShellExecute(0, 'open', weixin, None, None, 1)# 打开微信
            time.sleep(2)# 延迟两秒
            wei_tu = gui.locateOnScreen(config['wei_tu'])# 要双击的图片路径
            #gui.doubleClick(wei_tu)#双击该图片
            gui.click(wei_tu)#单击该图片
            print('微信已打开')
            continue
        # ----------------------------------------------------------------------
        if user_input[0:2] == '播放':
            def find_and_play(input_char):
                current_path = config['bfyinye']# 配置文件
                matching_files = [f for f in os.listdir(current_path) if input_char in f]
                matching_files.sort(key=lambda x: difflib.SequenceMatcher(None, input_char, x).ratio(), reverse=True)

                if matching_files:
                    print("匹配的文件:")
                    for i, file in enumerate(matching_files[:10]):
                        print(f"{i + 1}. {file}")

                    choice = int(input("请输入序号选择要播放的歌曲:")) - 1

                    if 0 <= choice < len(matching_files):
                        webbrowser.open(os.path.join(current_path, matching_files[choice]))
                        print(f"正在播放:{matching_files[choice]}")
                    else:
                        print("无效的选择,请重新输入。")
                else:
                    print("未找到匹配的文件。")

            music_name = user_input[3:]
            #music_name = input("请输入音乐名:")
            find_and_play(music_name)
            continue
        # ----------------------------------------------------------------------
        # 初始化最高匹配度
        max_score = -1
        best_answer = ""
        # 搜索匹配度最高的回答
        for i in range(len(questions)):
            score = get_match_score(user_input, questions[i])
            if score > max_score:
                max_score = score
                best_answer = answers[i]
            elif score == max_score:  # 处理相同匹配度的情况
                if random.randint(0, 100) == 100:  # 随机选择一条回答
                    best_answer = answers[i]

        # 输出回答逐个字符的方法
        if max_score == 0:
            bnhd = "陈文茜:我不理解你在说什么。"
            for bnhd1 in bnhd:
                print(bnhd1, end='')  # 每输出一个字符后立即刷新输出缓冲区
                time.sleep(0.05)  # 暂停0.1秒
            # print("")  # 输出完整回答后换行
        else:
            print("陈文茜:", end="")

            if best_answer is not None:  # if best_answer is not None:中的is not None用来判断你的表的答案是否为空
                for char in best_answer:  # 如果不为空则执行这个
                    print(char, end='', flush=True)  # 每输出一个字符后立即刷新输出缓冲区
                    time.sleep(0.05)  # 暂停0.1秒
            else:
                bnhd = "陈文茜:我不理解。"  # 为空则执行这个
                for bnhd1 in bnhd:
                    print(bnhd1, end='')  # 每输出一个字符后立即刷新输出缓冲区
                    time.sleep(0.05)  # 延迟0.1秒
        print("")  # 输出完整回答后换行
    # 记录程序结束时间
    end_time = time.time()
    end_localtime = time.localtime(end_time)
    end_strftime = time.strftime('%Y-%m-%d %H:%M:%S', end_localtime)

    # 写入程序结束时间和运行时长到日志文件
    log_file.write(f'[{end_strftime}] 程序已结束:运行时间: {end_time - start_time:.2f} 秒.\n')

    # 打印程序运行时长和结束时间
    elapsed_time = end_time - start_time
    elapsed_year = elapsed_time // (365 * 24 * 3600)
    elapsed_day = elapsed_time // (24 * 3600) % 365
    elapsed_hour = elapsed_time // 3600 % 24
    elapsed_minute = elapsed_time // 60 % 60
    elapsed_second = elapsed_time % 60
    print(f'运行时间: {elapsed_year} 年, {elapsed_day} 日, {elapsed_hour} 小时, {elapsed_minute} 分钟, {elapsed_second:.2f} 秒。')
    log_file.write(f'[{end_strftime}] 结束时间:{end_strftime} ')
    print("开始时间:", 开始时间)
    print(f'结束时间: {end_strftime}')

好了,就这样吧

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值