如何用Java写一个聊天机器人

您所在的位置:网站首页 怎么自己做一个qq群机器人 如何用Java写一个聊天机器人

如何用Java写一个聊天机器人

2024-07-10 13:44| 来源: 网络整理| 查看: 265

文章目录 建议结合新版教程看写在前面的的话免责声明你需要提前会的东西我们要使用的框架 首先我们先下载一个Demo文件配置Demo里面的的目录结构在配置文件中加上你小号的QQ名字和密码 我们加完mybatis之后的目录结构maven里面的配置为了防止SQL注入问题我们用德鲁伊连接池mybatis配置文件建立数据库Mybatis的映射文件Mybatis的mapper层mybatis的增删改查pojo层 工具类机器人的Talk(根据关键词从数据里面查询 如果查询到了就返回数据)机器人的Study学习功能机器人的删除功能 使用工具的模块类All_method这位更是重量级---- MyGropListen 群聊天监听一切的开始---启动类 首次登陆的时候出现滑动验证的问题咋办第一次的时候会弹出来一个弹窗 机器人效果上传到Linux服务器 并且运行

建议结合新版教程看

https://blog.csdn.net/qq_47431361/article/details/127365789

写在前面的的话

这是一个非常简单的聊天机器人的教程 本来我是不想写的(因为我是懒狗) 但是我在网上找不到类似的教程所以就自己打算写一个 这个机器人我只完成了最简单的功能

学习根据关键词来产生回复复读 还有很多其他的功能可以开发 但是因为我是懒狗所以我打算让我可爱的学弟去进行开发 在这里插入图片描述 如果你发现你的机器人群聊只能发送短字符并且机器人的私聊功能没有问题 那么你的机器人是被腾讯给风控了 这是正常的 解决方法是 你自己上机器人的QQ号多水群就行了 过一段时间风控就被解除了 免责声明

我不是大佬 我的水平也很低 里面实现的功能也是非常简单的功能(复杂的我也不会) 我从开始做到做完也就花了两天时间 对这个框架的很多功能也不是很了解 我的很多功能也是用很多的方法来实现的 如果你有更好的方法希望你也能写一篇教程让我也学习一下

你需要提前会的东西 最基本的MySQL一点点Linux的使用经验最简单的Mybatis的使用一点点使用Spring这种框架的经验(不会也没什么问题) 我们要使用的框架

我希望你在看这篇教程之前先提前看一下教学视频 起码看一下二十多分钟的 这个是框架的地址里面已经包含的有教程 框架地址 这里是写框架的老哥录的教学视频 可以说是非常详细了 这里是链接地址 如果你懒得看这个长的 起码你得看一下这个教学视频 稍微短一点的视频 这里面所提供的资料足够你自己完成一个机器人的开发了 但是这篇文章是面向纯纯的小白的所以会更加详细一点

首先我们先下载一个Demo

在教学视频里面已经嗦了Demo在哪下 为了避免小白找不到Demo在哪下我直接把这个Demo的下载链接贴到这里了

Demo地址

文件配置 Demo里面的的目录结构

在这里插入图片描述 视频里面已经对监听器里面的功能已经嗦的很明白了 而且demo里面已经打了很多很多的注释去解释功能了 你们看一下就知道怎么用了 在这里插入图片描述

在配置文件中加上你小号的QQ名字和密码

在这里插入图片描述 为了避免不必要的问题我建议你 在这里插入图片描述 在这两个文件里面都配置好 因为我实在不知道还有什么能嗦的所以我下面会讲怎么用Mybatis

我们加完mybatis之后的目录结构

在这里插入图片描述 在这里插入图片描述

maven里面的配置

因为要用一点新的东西 所以要在在这里插入图片描述 这个里面加一点点东西 因为我是懒狗所以我就不细嗦了 我直接把我的maven配置给放在这里了

4.0.0 simbot.example simbot-mirai-demo 1.0-SNAPSHOT 8 8 2.3.4 com.alibaba druid 1.1.10 org.mybatis mybatis 3.5.7 junit junit 4.12 test org.springframework spring-context 5.0.5.RELEASE org.springframework.boot spring-boot-starter-webflux 2.3.11.RELEASE mysql mysql-connector-java 5.1.47 com.alibaba druid 1.0.11 org.projectlombok lombok true 1.18.20 junit junit 4.12 org.slf4j slf4j-log4j12 1.6.4 com.baomidou mybatis-plus 3.1.1 love.forte.simple-robot component-mirai ${simbot.version} love.forte.simple-robot.time-task time-task-quartz ${simbot.version} com.alibaba fastjson 1.2.75 test src/main/resources **/*.properties **/*.yml **/*.xml **/*.tld **/*.** false src/main/java **/*.properties **/*.yml **/*.xml **/*.tld false org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 org.springframework.boot spring-boot-maven-plugin 2.5.3 love.simbot.example.SimbotExampleApplication repackage 为了防止SQL注入问题我们用德鲁伊连接池

在这里插入图片描述 我们整一个druid文件夹 创建一个MyDruid

package love.simbot.example.druid; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; import org.apache.ibatis.datasource.DataSourceFactory; import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory; import javax.sql.DataSource; import java.sql.SQLException; import java.util.Properties; public class MyDruid implements DataSourceFactory { private Properties props; @Override public DataSource getDataSource() { DruidDataSource dds = new DruidDataSource(); dds.setDriverClassName(this.props.getProperty("driver")); dds.setUrl(this.props.getProperty("url")); dds.setUsername(this.props.getProperty("username")); dds.setPassword(this.props.getProperty("password")); try { dds.init(); } catch (SQLException e) { e.printStackTrace(); } return dds; } @Override public void setProperties(Properties props) { this.props = props; } } mybatis配置文件 建立数据库

在这里插入图片描述 在这里插入图片描述 建立表这个就没什么值得细嗦的了 实在不会建表就直接右键建就完事了

Mybatis的映射文件

在这里插入图片描述

DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> insert into kv values(NULL,#{key},#{value}); delete from kv where id=#{id} SELECT * FROM kv WHERE `key`=#{key} SELECT * FROM kv WHERE `key`=#{key} Mybatis的mapper层

在这里插入图片描述

package love.simbot.example.mybatis.mapper; import love.simbot.example.mybatis.pojo.Key_Value; import org.apache.ibatis.annotations.Param; import java.util.ArrayList; public interface Key_Value_Mapper { int insertKV(@Param("key")String key,@Param("value")String value); Key_Value get_One_KV_ByKey(@Param("key")String key); ArrayList get_Some_KV_ByKey(@Param("key")String key); int deleteKV(@Param("id")int id); } mybatis的增删改查

因为我是懒狗(主要原因) 而且我感觉没什么写改的必要 所以我没写改的方法

pojo层

在这里插入图片描述

package love.simbot.example.mybatis.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor @TableName("Key_Value") public class Key_Value { @TableId(type = IdType.AUTO) private int id; private String key; public String value; } 工具类 机器人的Talk(根据关键词从数据里面查询 如果查询到了就返回数据)

这个Talk是根据机器人对于群聊监听获得的字符串然后跟数据库里面的key进行匹配 如果匹配到了就返回匹配到的value 如果匹配到了多个key就随机返回一个value 比如说数据库里面有这样的k v k1 v1 k1 v2 如果接收到了k1 他会从数据库里面拿到两个字符串 v1 v2 然后随机返回一个String类型

package love.simbot.example.mybatis.controller; import love.simbot.example.mybatis.mapper.Key_Value_Mapper; import love.simbot.example.mybatis.pojo.Key_Value; import java.io.IOException; import java.util.ArrayList; public class Talk { Key_Value_Mapper userMapper; public Talk( Key_Value_Mapper userMapper) { this.userMapper=userMapper; } public String QQbot_Talk(String key) throws IOException { ArrayList some_kv_byKey = userMapper.get_Some_KV_ByKey(key); int size = some_kv_byKey.size(); if (size ==0){ return "0"; }else if(size ==1){ Key_Value key_value = some_kv_byKey.get(size-1); return key_value.getValue(); }else { final double d = Math.random(); final int i = (int)(d*size); Key_Value key_value = some_kv_byKey.get(i); return key_value.getValue(); } } } 机器人的Study学习功能 package love.simbot.example.mybatis.controller; import love.simbot.example.mybatis.mapper.Key_Value_Mapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; public class Study { Key_Value_Mapper userMapper=null; public Study(Key_Value_Mapper userMapper) { this.userMapper = userMapper; } public String QQbot_Study(String key, String value) throws IOException { int i = userMapper.insertKV(key, value); if (i ==0){ return "学习失败"; }else { return "学习完毕"; } } } 机器人的删除功能

因为我是懒狗 所以虽然做了删除功能的模块但是我没有装到机器人里面

package love.simbot.example.mybatis.controller; import love.simbot.example.mybatis.mapper.Key_Value_Mapper; import love.simbot.example.mybatis.pojo.Key_Value; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; public class Delete_Study { Key_Value_Mapper key_value_mapper=null; public Delete_Study(Key_Value_Mapper key_value_mapper) { this.key_value_mapper = key_value_mapper; } public ArrayList QQbot_Delete_What_you_want(String key) throws IOException { ArrayList some_kv_byKey = key_value_mapper.get_Some_KV_ByKey(key); return some_kv_byKey; } public String QQbot_Delete_By_Id(int id){ int i = key_value_mapper.deleteKV(id); return "id为:"+String.valueOf(i)+"的信息已经被删除力"; } } 使用工具的模块类All_method

这里面有一个检测是否是url的一个方法 本来我打算做一个talk检测图片然后如果是图片的话就发送图片 但是这个功能完成了一半我就没往下面写了 如果问为什么的话 答案只有一个 那就是我是懒狗

package love.simbot.example.mybatis.controller; import love.simbot.example.mybatis.mapper.Key_Value_Mapper; import love.simbot.example.mybatis.pojo.Key_Value; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public class All_method { InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); //创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象 SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is); //创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务 //SqlSession sqlSession = sqlSessionFactory.openSession(); //创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交 SqlSession sqlSession = sqlSessionFactory.openSession(true); //通过代理模式创建UserMapper接口的代理实现类对象 Key_Value_Mapper userMapper = sqlSession.getMapper(Key_Value_Mapper.class); public All_method() throws IOException { } //调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配 public String study(String key,String value) throws IOException { Study study = new Study(userMapper); return study.QQbot_Study(key, value); } public ArrayList select_By_key(String key){ ArrayList some_kv_byKey = userMapper.get_Some_KV_ByKey(key); return some_kv_byKey; } public String talk(String key) throws IOException { Talk talk = new Talk(userMapper); return talk.QQbot_Talk(key); } public String delete_By_Id(int id){ Delete_Study delete_study = new Delete_Study(userMapper); return delete_study.QQbot_Delete_By_Id(id); } public static boolean isUrl(String urls) { String regex = "(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\&%\\+\\$#_=]*)?"; Pattern pat = Pattern.compile(regex); Matcher mat = pat.matcher(urls.trim()); boolean result = mat.matches(); return result; } } 这位更是重量级---- MyGropListen 群聊天监听 package love.simbot.example.listener; import catcode.CatCodeUtil; import catcode.Neko; import love.forte.common.ioc.annotation.Beans; import love.forte.simbot.annotation.Filter; import love.forte.simbot.annotation.OnGroup; import love.forte.simbot.annotation.OnPrivate; import love.forte.simbot.api.message.MessageContent; import love.forte.simbot.api.message.containers.GroupAccountInfo; import love.forte.simbot.api.message.containers.GroupInfo; import love.forte.simbot.api.message.events.GroupMsg; import love.forte.simbot.api.message.events.PrivateMsg; import love.forte.simbot.api.sender.MsgSender; import love.forte.simbot.api.sender.Sender; import love.forte.simbot.filter.MatchType; import love.simbot.example.mybatis.controller.All_method; import love.simbot.example.mybatis.pojo.Key_Value; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * 群消息监听的示例类。 * 所有需要被管理的类都需要标注 {@link Beans} 注解。 * @author ForteScarlet */ @Beans public class MyGroupListen { final static String IMG="图片的url地址"; private All_method all_method; { try { all_method = new All_method(); } catch (IOException e) { e.printStackTrace(); } } /** log */ private static final Logger LOG = LoggerFactory.getLogger(MyGroupListen.class); /** * 此监听函数代表,收到消息的时候,将消息的各种信息打印出来。 * * 此处使用的是模板注解 {@link OnGroup}, 其代表监听一个群消息。 * * 由于你监听的是一个群消息,因此你可以通过 {@link GroupMsg} 作为参数来接收群消息内容。 * *

* 注意! 假如你发现你群消息发不出去(或者只有一些很短的消息能发出去)且没有任何报错, * 但是尝试后,发现 私聊 一切正常,能够发送,那么这是 正常现象! * * 参考: * */ @OnGroup public void onGroupMsg(GroupMsg groupMsg,MsgSender sender) { // 打印此次消息中的 纯文本消息内容。 // 纯文本消息中,不会包含任何特殊消息(例如图片、表情等)。 System.out.println(groupMsg.getText()); String text = groupMsg.getText(); String talk; try { talk = all_method.talk(text); boolean url = all_method.isUrl(talk); System.out.println("触发了查询关键词"+talk); System.out.println("".equals(talk)==false); System.out.println("0".equals(talk)==false); if (url){ if ("".equals(talk)==false&&"0".equals(talk)==false) { CatCodeUtil util = CatCodeUtil.INSTANCE; String img = util.getStringTemplate().image(IMG); sender.SENDER.sendGroupMsg(groupMsg, "图片" + talk); } } else { String t=talk; if ("".equals(talk)==false&&"0".equals(talk)==false){ sender.SENDER.sendGroupMsg(groupMsg,t); } } } catch (IOException e) { System.out.println("未找到关键词"); } // 打印此次消息中的 消息内容。 // 消息内容会包含所有的消息内容,也包括特殊消息。特殊消息使用CAT码进行表示。 // 需要注意的是,绝大多数情况下,getMsg() 的效率低于甚至远低于 getText() System.out.println(groupMsg.getMsg()); // 获取此次消息中的 消息主体。 // messageContent代表消息主体,其中通过可以获得 msg, 以及特殊消息列表。 // 特殊消息列表为 List, 其中,Neko是CAT码的封装类型。 MessageContent msgContent = groupMsg.getMsgContent(); // 打印消息主体 System.out.println(msgContent); // 打印消息主体中的所有图片的链接(如果有的话) List imageCats = msgContent.getCats("image"); System.out.println("img counts: " + imageCats.size()); for (Neko image : imageCats) { System.out.println("Img url: " + image.get("url")); } // 获取发消息的人。 GroupAccountInfo accountInfo = groupMsg.getAccountInfo(); // 打印发消息者的账号与昵称。 System.out.println(accountInfo.getAccountCode()); System.out.println(accountInfo.getAccountNickname()); // 获取群信息 GroupInfo groupInfo = groupMsg.getGroupInfo(); // 打印群号与名称 System.out.println(groupInfo.getGroupCode()); System.out.println(groupInfo.getGroupName()); } @OnGroup @Filter(value="nana学习",trim=true,matchType = MatchType.CONTAINS) public void study(GroupMsg groupMsg, MsgSender sender) { String text = groupMsg.getText(); String[] split = text.split("\\s+"); String key=split[1]; String value=split[2]; System.out.println("图片是"+value); MessageContent msgContent = groupMsg.getMsgContent(); List imageCats = msgContent.getCats("image"); System.out.println("img counts: " + imageCats.size()); // for (Neko image : imageCats) { // System.out.println("Img url: " + image.get("url")); // } // if (imageCats!=null){ // for (Neko imageCat : imageCats) { // try { // all_method.study(key,imageCat.get("url")); // } catch (IOException e) { // sender.SENDER.sendGroupMsg(groupMsg,"图片学习出问题 "); // e.printStackTrace(); // } // sender.SENDER.sendGroupMsg(groupMsg,"图片学习完成"); // } // }else{ try { all_method.study(key,value); } catch (IOException e) { sender.SENDER.sendGroupMsg(groupMsg,"学习出问题 "); e.printStackTrace(); } sender.SENDER.sendGroupMsg(groupMsg,"学习完成"); // sender.SENDER.sendGroupMsg(groupMsg,groupMsg.getMsgContent()); // } } @OnGroup @Filter(value="hi",trim=true,matchType = MatchType.CONTAINS) public void hello(GroupMsg groupMsg, MsgSender sender) { sender.SENDER.sendGroupMsg(groupMsg,"我接收到了hi "); // sender.SENDER.sendGroupMsg(groupMsg,groupMsg.getMsgContent()); } @OnGroup @Filter(value="测试复读",trim=true,matchType = MatchType.CONTAINS) public void replyPrivateMsg1(GroupMsg privateMsg, MsgSender sender) { // 获取消息正文。 String text = privateMsg.getText(); System.out.println(text); // 向 privateMsg 的账号发送消息,消息为当前接收到的消息。 sender.SENDER.sendGroupMsg(privateMsg, text); System.out.println("发送完毕"); } final String ac="测试回复"; @OnGroup @Filter(value=ac,trim=true,matchType = MatchType.CONTAINS,atBot = true) public void img(GroupMsg privateMsg, MsgSender sender) { CatCodeUtil util= CatCodeUtil.INSTANCE; String img= util.getStringTemplate().image(IMG); sender.SENDER.sendGroupMsg(privateMsg,"图片"+img); } final static String IMG1="https://image.16pic.com/00/53/26/16pic_5326745_s.jpg?imageView2/0/format/png"; @OnGroup @Filter(value="图片test",trim=true,matchType = MatchType.CONTAINS) public void Grop_msg(GroupMsg privateMsg, MsgSender sender) { CatCodeUtil util= CatCodeUtil.INSTANCE; String img= util.getStringTemplate().image(IMG1); sender.SENDER.sendGroupMsg(privateMsg,"图片"+img); } } 一切的开始—启动类 package love.simbot.example; import love.forte.common.configuration.Configuration; import love.forte.simbot.annotation.SimbotApplication; import love.forte.simbot.annotation.SimbotResource; import love.forte.simbot.api.sender.BotSender; import love.forte.simbot.bot.Bot; import love.forte.simbot.core.SimbotApp; import love.forte.simbot.core.SimbotContext; import love.forte.simbot.core.SimbotProcess; import org.jetbrains.annotations.NotNull; import java.time.LocalDateTime; /** * simbot 启动类。 *

* 此处的注解配置了两个配置文件: * * simbot.yml * simbot-dev.yml * * 其中,{@code simbot-dev.yml} 是一个测试环境的配置文件,只有当启动参数中存在 {@code --Sdev} 的时候才会被使用。 * 如果你不需要一些特殊的配置文件,那么可以直接使用 {@code @SimbotApplication}. *

* 默认情况下,默认的配置文件名称为 {@code simbot.yml} 或 {@code simbot.properties} * * @author ForteScarlet */ @SimbotApplication({ @SimbotResource(value = "simbot.yml", orIgnore = true), @SimbotResource(value = "simbot-dev.yml", orIgnore = true, command = "dev"), }) // @SimbotApplication public class SimbotExampleApplication implements SimbotProcess { public static void main(String[] args) { /* run方法的第一个参数是一个标注了@SimbotApplication注解的启动类。 第二个参数是main方法得到的启动参数。 */ SimbotApp.run(SimbotExampleApplication.class, args); } /** * * 启动后 */ @Override public void post(@NotNull SimbotContext context) { Bot bot = context.getBotManager().getDefaultBot(); BotSender sender = bot.getSender(); sender.SENDER.sendPrivateMsg("发送的qq号","已经启动完毕了 当前启动时间是"+ LocalDateTime.now()); } /** * * 启动前 */ @Override public void pre(@NotNull Configuration config) { } }

你点一下这个小三角机器人就开始运行了 在这里插入图片描述

首次登陆的时候出现滑动验证的问题咋办

Github地址 在这里插入图片描述 请添加图片描述

第一次的时候会弹出来一个弹窗

你把弹窗里面的请求码地址放到这里面 然后点击下一步 会出现一个滑动验证码 你滑动之后在看那个弹窗 弹窗里面会有一个四位数的数字 你再把数字给再输进到这里面 在这里插入图片描述 然后你再点击下一步就好了 你这个电脑的信息就已经写进一个文件夹里面了 等你打成jar包之后这些信息都会带进去 也就是说你这个jar包以后无论在哪跑腾讯服务器都会认为这个QQ号登陆的就是在你验证的这个电脑上面 也就不用再重复搞这个验证了

机器人效果

登陆成功效果 在这里插入图片描述

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

上传到Linux服务器 并且运行

在这里插入图片描述 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3