V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yaphone
V2EX  ›  程序员

itchat4j -- 扩展个人微信号的能力

  •  
  •   yaphone · 2017-04-30 01:54:53 +08:00 · 3721 次点击
    这是一个创建于 2754 天前的主题,其中的信息可能已经有所发展或是发生改变。

    itchat4j -- 用 Java 扩展个人微信号的能力

    项目地址:itchat4j,该项目长期维护更新,欢迎 star、fork、pull requests、issue。

    来源

    itchat 是一个非常优秀的开源微信个人号接口,使用 Python 语言开发,提供了简单易用的 API,可以很方便地对个人微信号进行扩展,实现自动回复,微信挂机机器人等,一直在关注这个项目,基于 itchat 开发过一个小项目,用来控制我的树莓派来播放音乐,效果还不错。

    一直想实现一个 java 版本的 itchat,由于工作太忙导致一拖再拖,这段时间稍微空闲了一些,仔细阅读了 itchat 的源码,终于完成了一个基础版本,由于主要灵感来源于 itchat 项目,所以这个项目的就暂时定名为itchat4j吧。

    项目介绍

    itchat 是一个开源的微信个人号接口,使用 Java 调用微信从未如此简单。使用短短的几十行代码,你就可以完成一个能够处理所有信息的微信机器人。当然,itchat 的使用远不止一个机器人,更多的功能等着你来发现,如今微信已经成为了个人社交的很大一部分,希望这个项目能够帮助你扩展你的个人的微信号、方便自己的生活。(引自 itchat 项目)

    你可以轻松将itchat4j其集成在你个人的 Java 应用中,无论是 SpringMVC、桌面程序还是嵌入式程序,只要使用的 JDK 是 1.5 以上的版本,都可以轻松接入。玩法很多,请打开你的脑洞,比如这些:

    • Just for fun,把个人微信号扩展为"公众号",在朋友面前装个 X 吧。
    • 集成在你的个人应用( SpringMVC、Serverlet、GUI )中,为应用提供更强的服务能力。
    • 部署在你的服务器上,将监控信息、日志发送到你的微信号。
    • 微信机器人,专业陪聊工具
    • 控制智能家居、智能硬件等具有开放接口的设备
    • Anything you want ...

    如何使用

    itchat4j 是一个 Maven 项目,下载源码后,可以以 Maven 项目的形式导入,导入后的项目结构如下图:

    itchat4j 项目结构

    src/main/java 是 itchat4j 的项目源码,在 src/test/java 目录下有两个小 Demo:一个是基本功能的小示例,当前,itchat4j 可以处理四类基本信息,文本、语音、图片和小视频,该示例在收到文本信息后自动回复,回复内容为收到的文本,当收到图片、语音、小视频时可以保存到指定的目录;一个是微信接入图灵机器人的小例子,让你的个人微信号摇身一变,成为一个小小的"公众号",百闻不如一见,我把这个图灵机器人的小 Demo 部署到了我的阿里云服务器上,现在就扫码体验一下吧。

    二维码

    微信机器人使用截图

    微信机器人

    控制台收到的消息

    简单入门教程

    接下来,通过两个小 Demo 来演示一下如何使用 itchat4j 来扩展你的个人微信号,入门教程的项目源码可以从此处下载

    Demo1: SimpleDemo

    这个小 Demo 将会将收到的文本消息发送给发件人,如果是图片、语音或者小视频消息,将会保存在我们指定的路径下。

    首先需要新建一个类来实现IMsgHandlerFace这个接口,这个类要做的就是我们需要完成的逻辑,该接口有四个方法需要实现,textMsgHandle用于处理文本信息,picMsgHandle用于处理图片信息,viedoMsgHandle用于处理小视频信息,voiceMsgHandle用于处理语音信息,代码如下:

    public class MsgHandler implements IMsgHandlerFace {
    
    	@Override
    	public String picMsgHandle(JSONObject arg0) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    	@Override
    	public String textMsgHandle(JSONObject arg0) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    	@Override
    	public String viedoMsgHandle(JSONObject arg0) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    	@Override
    	public String voiceMsgHandle(JSONObject arg0) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    }
    

    由于没有关联源码,所以接口中的参数都变成了arg0这种,建议关联一下源码,源码可在release中下载,当然不关联也不会有啥影响,arg0其实是我们需要处理的消息体,为了更直观,建议把arg0修改为msg,msg 是 fastjson 的 JSONObject 类型,这个其实不用关心,我们只需要知道如何来获取需要的消息就可以了,下面的 Demo 中有示例。然后我们来写处理逻辑。

    textMsgHandler中,通过msg.getString("Text")就可以获取收到的文本信息,然后作进一步处理,比如接入图灵机器人、消息自动回复等,我们需要在这个方法中返回一个字符串,即是需要回复给好友的消息,在 SimpleDemo 这个示例中,我们直接回复收到的原文本消息。

    picMsgHandlevoiceMsgHandleviedoMsgHandle这三个方法中,我们需要将这些消息下载下来,然后再作进一步处理,所以需要为每种类型的消息提供一个保存路径,然后调用DownloadTools.getDownloadFn方法可以将这三种类型的消息下载下来。DownloadTools.getDownloadFn方法提供下载图片、语音、小视频的功能,需要三个参数,第一个参数为我们收到的 msg,第二个参数为MsgType,也就是消息类型,图片、语音、小视频分别对应MsgType.PICMsgType.VOICEMsgType.VOICE,然后第三个参数就是保存这些消息的路径了。

    就不多说了,让代码和注释君自述吧,有不明白的地方,可以在 Issue 中提出来。

    /**
     * 简单示例程序,收到文本信息自动回复原信息,收到图片、语音、小视频后根据路径自动保存
     * 
     * @author https://github.com/yaphone
     * @date 创建时间:2017 年 4 月 28 日 下午 10:50:36
     * @version 1.0
     *
     */
    public class SimpleDemo implements IMsgHandlerFace {
    
    	@Override
    	public String textMsgHandle(JSONObject msg) {
    		String text = msg.getString("Text");
    		return text;
    	}
    
    	@Override
    	public String picMsgHandle(JSONObject msg) {
    		String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".jpg"; // 这里使用收到图片的时间作为文件名
    		String picPath = "D://itchat4j/pic" + File.separator + fileName; // 保存图片的路径
    		DownloadTools.getDownloadFn(msg, MsgType.PIC, picPath); // 调用此方法来保存图片
    		return "图片保存成功";
    	}
    
    	@Override
    	public String voiceMsgHandle(JSONObject msg) {
    		String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".mp3"; // 这里使用收到语音的时间作为文件名
    		String voicePath = "D://itchat4j/voice" + File.separator + fileName; // 保存语音的路径
    		DownloadTools.getDownloadFn(msg, MsgType.VOICE, voicePath); // 调用此方法来保存语音
    		return "声音保存成功";
    	}
    
    	@Override
    	public String viedoMsgHandle(JSONObject msg) {
    		System.out.println(msg);
    		String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".mp4"; // 这里使用收到小视频的时间作为文件名
    		String viedoPath = "D://itchat4j/viedo" + File.separator + fileName;// 保存小视频的路径
    		DownloadTools.getDownloadFn(msg, MsgType.VIEDO, viedoPath);// 调用此方法来保存小视频
    		return "视频保存成功";
    	}
    
    }
    

    之后我们需要将实现IMsgHandlerFace接口的类 [注入] 到Wechat中来启动服务,Wechat是服务的主入口,其构造函数接受两个参数,一个是我们刚才实现IMsgHandlerFace接口的类,另一个是保存登陆二维码图片的路径。之后在Wechat对象上调用start()方法来启动服务,会在我们刚才传入的路径下生成一个QR.jpg文件,即是登陆二维码,通过手机微信扫描后即可登陆,服务启动,处理逻辑开始工作。这里有一点需要注意:二维码图片如果超过一定时间未扫描会过期,过期时会自动更新,所以你可能需要重新打开图片

    额,文字还是太苍白,让代码和注释君自述吧。

    /**
     * 
     * @author https://github.com/yaphone
     * @date 创建时间:2017 年 4 月 28 日 上午 12:44:10
     * @version 1.0
     *
     */
    public class Mytest {
    	public static void main(String[] args) {
    		String qrPath = "D://itchat4j//login"; // 保存登陆二维码图片的路径
    		IMsgHandlerFace msgHandler = new SimpleDemo(); // 实现 IMsgHandlerFace 接口的类
    		Wechat wechat = new Wechat(msgHandler, qrPath); //  [注入] 
    		wechat.start(); // 启动服务,会在 qrPath 下生成一张二维码图片,扫描即可登陆,注意,二维码图片如果超过一定时间未扫描会过期,过期时会自动更新,所以你可能需要重新打开图片
    	}
    }
    

    Demo2 图灵机器人

    图灵机器人大脑具备强大的中文语义分析能力,可准确理解中文含义并作出回应,是最擅长聊中文的机器人大脑,赋予软硬件产品自然流畅的人机对话能力。(引自百度百科)

    这个示例中我们接入图灵机器人的 API,将收到的好友的文本信息发送给图灵机器人,并将机器人回复的消息发送给好友,接下来还是把舞台交代码和注释君吧。

    /**
     * 图灵机器人示例
     * 
     * @author https://github.com/yaphone
     * @date 创建时间:2017 年 4 月 24 日 上午 12:13:26
     * @version 1.0
     *
     */
    public class TulingRobot implements IMsgHandlerFace {
    
    	MyHttpClient myHttpClient = new MyHttpClient();
    	String apiKey = "597b34bea4ec4c85a775c469c84b6817"; // 这里是我申请的图灵机器人 API 接口,每天只能 5000 次调用,建议自己去申请一个,免费的:)
    	Logger logger = Logger.getLogger("TulingRobot");
    
    	@Override
    	public String textMsgHandle(JSONObject msg) {
    		String result = "";
    		String text = msg.getString("Text");
    		String url = "http://www.tuling123.com/openapi/api";
    		Map<String, String> paramMap = new HashMap<String, String>();
    		paramMap.put("key", apiKey);
    		paramMap.put("info", text);
    		paramMap.put("userid", "123456");
    		String paramStr = JSON.toJSONString(paramMap);
    		try {
    			HttpEntity entity = myHttpClient.doPost(url, paramStr);
    			result = EntityUtils.toString(entity, "UTF-8");
    			JSONObject obj = JSON.parseObject(result);
    			if (obj.getString("code").equals("100000")) {
    				result = obj.getString("text");
    			} else {
    				result = "处理有误";
    			}
    		} catch (Exception e) {
    			logger.info(e.getMessage());
    		}
    		return result;
    	}
    
    	@Override
    	public String picMsgHandle(JSONObject msg) {
    
    		return "收到图片";
    	}
    
    	@Override
    	public String voiceMsgHandle(JSONObject msg) {
    
    		return "收到语音";
    	}
    
    	@Override
    	public String viedoMsgHandle(JSONObject msg) {
    
    		return "收到视频";
    	}
    
    	public static void main(String[] args) {
    		IMsgHandlerFace msgHandler = new TulingRobot();
    		Wechat wechat = new Wechat(msgHandler, "/home/itchat4j/demo/itchat4j/login");
    		wechat.start();
    	}
    
    }
    

    Demo3 itchat4j 集成在 SpringMVC 应用中

    这个示例要讲起来就比较困难了,因为 SpringMVC 本身就是一个复杂的东西,先在这里挖个坑吧。其实在 SpringMVC 中集成与上面两个示例并没有太大的不同,我的个人博客是基于 SpringMVC 的,我已经将集成在这个项目里了,这样我就可以通过微信来更新我的博客了。详细的就不多说了,大家先看看这个项目结构吧。

    itchat4j 集成在 Blog 项目

    其中MsgHandler就是我处理微信消息的逻辑,略复杂,就不贴代码了。WechatService就是将MsgHandler“注入”到Wechat类中,与上面两个示例的作用是一样的,贴一下WechatService的代码:

    /**
     * Wechat 服务实现类
     * 
     * @author https://github.com/yaphone
     * @date 创建时间:2017 年 4 月 29 日 下午 7:44:01
     * @version 1.0
     *
     */
    @Service("wechatService")
    public class WechatService implements IWechatServiceFace {
    	@Value("${qrPath}")
    	private String qrPath;
    
    	@Override
    	public void login() {
    		MsgHandler msgHandler = new MsgHandler();
    		Wechat wechat = new Wechat(msgHandler, qrPath);
    		wechat.start();
    	}
    }
    
    

    类似项目

    itchat :优秀的、基于 Python 的微信个人号 API,同时也是本项目的灵感之源。

    问题和建议

    本项目长期更新、维护,功能不断扩展与完善中,欢迎 star。

    项目使用过程中遇到问题,欢迎随时反馈。

    任何问题或者建议都可以在 Issue 中提出来,也可以加入 QQ 群讨论:636365179

    11 条回复    2017-04-30 22:09:28 +08:00
    lcqtdwj
        1
    lcqtdwj  
       2017-04-30 02:53:41 +08:00
    nice,最近正学 java,学习一下
    mahone3297
        2
    mahone3297  
       2017-04-30 06:06:37 +08:00
    python ?怎么看,代码都是 java 啊
    lloovve
        3
    lloovve  
       2017-04-30 06:19:31 +08:00 via iPhone
    所有 itchat 功能都有吗
    ob
        4
    ob  
       2017-04-30 08:53:28 +08:00 via Android
    微信 api 接口,消息处理这块一般没什么问题,经常出问题的地方是登录,检测心跳,选择线路这几个地方,这几个地方要做容错机制,当这几个地方出错时,怎么让微信又自动连接上,楼主对这块有专门处理吗?
    而且很多用户都是用国外的 vps,链接微信服务器的速度不比国内。
    LuckCode
        5
    LuckCode  
       2017-04-30 08:58:15 +08:00 via iPhone
    学习一下,学渣刚好准备入坑 java
    yaphone
        6
    yaphone  
    OP
       2017-04-30 09:51:07 +08:00
    @mahone3297 itchat 是基于 python 的,itchat4j 是使用 java 语言
    yaphone
        7
    yaphone  
    OP
       2017-04-30 09:51:26 +08:00
    @lcqtdwj 欢迎关注!
    yaphone
        8
    yaphone  
    OP
       2017-04-30 09:52:08 +08:00
    @lloovve 还没有,目前只能处理文本、语音、图片、小视频消息,功能正在不断完善。
    yaphone
        9
    yaphone  
    OP
       2017-04-30 09:54:22 +08:00
    @ob 心跳检测是参照原项目来写的,目前心跳正常,线路在 itchat 中一共看到五个,有一个可能已经过期了,可能还有漏掉的,后面发现的话会补上,重连机制目前还没有实现,多谢你的建议!
    defunct9
        10
    defunct9  
       2017-04-30 10:00:44 +08:00 via iPhone
    能发送名片吗?
    yaphone
        11
    yaphone  
    OP
       2017-04-30 22:09:28 +08:00
    @defunct9 预计下一个版本会加入该功能
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5421 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 07:10 · PVG 15:10 · LAX 23:10 · JFK 02:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.