前言:java.awt.Robot可以控制鼠标和键盘,本文基于此通过模拟认为添加微信好友的过程实现批量添加微信好友,并最终输出微信号/手机号是否有好友及好友的基本信息,本文代码示例禁用学习交流使用;

1 批量添加好友代码:
1.1 从txt 读取要搜索的好友并添加 AutoAddBat:

package org.example.wechat;/*** 微信添加好友工具** @Description TODO* @Date 2023/2/2 16:19* @Author lgx* @Version 1.0*/import org.example.wechat.dto.FriendBaseDto;
import org.example.wechat.enums.FriendSourceTypeEnum;import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;public class AutoAddBat {// 微信界面坐标点static Map<String, List<Integer>> mapPostion = new LinkedHashMap<>(100);// 添加好友时填写的备注信息static Map<String, String> mapMyMsg = new LinkedHashMap<>(10);/*** 微信界面操作坐标点初始化* 注意:微信窗口每次被移动后都需要进行坐标位置的更新*/static {mapPostion.put("添加好友按钮", getPostion(608, 165));mapPostion.put("输入内容搜索好友", getPostion(437, 169));mapPostion.put("点击搜索好友", getPostion(533, 228));mapPostion.put("复制搜索好友的昵称位置", getPostion(774, 226));mapPostion.put("复制搜索好友的昵称复制位置", getPostion(780, 235));mapPostion.put("复制搜索好友的地区位置", getPostion(789, 249));mapPostion.put("复制搜索好友的地区复制位置", getPostion(810, 260));mapPostion.put("添加清除上一次搜索好友按钮", getPostion(574, 168));mapPostion.put("添加通讯录按钮", getPostion(777, 336));mapPostion.put("填写发送添加朋友申请", getPostion(1035, 336));mapPostion.put("填写备注名", getPostion(1035, 415));mapPostion.put("填写标签", getPostion(1035, 487));mapPostion.put("确定添加好友", getPostion(857, 806));mapPostion.put("取消添加好友", getPostion(971, 826));mapMyMsg.put("添加朋友申请信息", "我是 xxxx");mapMyMsg.put("添加朋友备注信息", "他是 xxxx");mapMyMsg.put("添加朋友标签信息", "他所在的标签");}private static List<Integer> getPostion(int postionOne, int postionTwo) {List<Integer> postions = new ArrayList<>(2);postions.add(postionOne);postions.add(postionTwo);return postions;}public static void main(String[] args) throws InterruptedException {// 获取要搜索的List<FriendBaseDto> searchFriends = getSearchFriend(FriendSourceTypeEnum.从txt导入, "F:\\addwechat\\addWechatSource.txt");if (null == searchFriends || searchFriends.isEmpty()) {System.out.println("没有好友需要被添加");}AtomicBoolean isFirst = new AtomicBoolean(true);Robot robot = getRobot();searchFriends.stream().forEach(e -> {// 添加好友try {addFriendByOnece(robot, isFirst.get(), e);} catch (Exception ex) {e.setErrorMsg(ex.getMessage());}isFirst.set(false);});searchFriends.stream().forEach(e->{if (!e.isHasFriend()){System.out.println(e.getFriendSearch() + ":没有搜索到对应的好友");}else {System.out.print(e.getFriendSearch() + ":有对应的好友,");System.out.println("对应好友信息:"+e.toString());}});}/*** 获取要搜索的好友** @param typeEnum* @return*/private static List<FriendBaseDto> getSearchFriend(FriendSourceTypeEnum typeEnum, String fileUrl) {List<FriendBaseDto> friendBaseDtos = new ArrayList<>(1000);switch (typeEnum) {case 从txt导入://friendBaseDtos.addAll(getSourceFriendBytxt(fileUrl));break;case 从docx导入:break;case 从excel导入:break;case 自定义:break;}return friendBaseDtos;}/*** 从txt导入** @param fileName* @return*/private static Collection<? extends FriendBaseDto> getSourceFriendBytxt(String fileName) {List<FriendBaseDto> friendBaseDtos = new ArrayList<>(1000);try {File myFile = new File(fileName);//通过字符串创建File类型对象,指向该字符串路径下的文件if (myFile.isFile() && myFile.exists()) { //判断文件是否存在InputStreamReader Reader = new InputStreamReader(new FileInputStream(myFile), "UTF-8");//考虑到编码格式,new FileInputStream(myFile)文件字节输入流,以字节为单位对文件中的数据进行读取//new InputStreamReader(FileInputStream a, "编码类型")//将文件字节输入流转换为文件字符输入流并给定编码格式BufferedReader bufferedReader = new BufferedReader(Reader);//BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。//通过BuffereReader包装实现高效读取String lineTxt = null;FriendBaseDto oneDto = null;while ((lineTxt = bufferedReader.readLine()) != null) {//buffereReader.readLine()按行读取写成字符串if ("".equals(lineTxt)) {continue;}// System.out.println(lineTxt);oneDto = new FriendBaseDto();oneDto.setFriendSearch(lineTxt.trim());friendBaseDtos.add(oneDto);}Reader.close();} else {System.out.println("找不到指定的文件");}} catch (Exception e) {System.out.println("读取文件内容出错");e.printStackTrace();}return friendBaseDtos;}/*** 添加微信好友** @param robot*/private static void addFriendByOnece(Robot robot, boolean isFirst, FriendBaseDto oneFriend) {if (isFirst) {// 第一次 打开微信openWxWindow(robot);}// 搜索好友startAddFrendOne(robot, oneFriend.getFriendSearch(), isFirst);// 搜索到的好友信息Map<String, Object> msgFriend = getFriendMsg(robot);// 判断是否搜索到对应的好友if (!(Boolean) msgFriend.get("hasFriend")) {// 没有好友// System.out.println("friendNickName+\"没有对应好友\" = " + oneFriend.getFriendSearch() + "没有对应好友");oneFriend.setHasFriend(false);return;}// 输出好友信息oneFriend.setHasFriend(true);msgFriend.entrySet().stream().forEach(e -> {System.out.println("e.getKey() +\":\"+e.getValue() = " + e.getKey() + ":" + e.getValue());});oneFriend.setNickName(msgFriend.get("昵称") + "");oneFriend.setArea(msgFriend.get("地区") + "");// 添加好友Map<String, Object> addFriendResult = addFriend(robot);// 输出结果addFriendResult.entrySet().stream().forEach(e -> {System.out.println("e.getKey() +\":\"+e.getValue() = " + e.getKey() + ":" + e.getValue());});oneFriend.setApplyMsg(addFriendResult.get("设置申请的信息") + "");oneFriend.setFriendRemark(addFriendResult.get("设置备注名称") + "");oneFriend.setFriendLabel(addFriendResult.get("设置标签") + "");}/*** 打开微信*/private static void openWxWindow(Robot robot) {//打开微信 Ctrl+Alt+Wassert robot != null;robot.keyPress(KeyEvent.VK_CONTROL);robot.keyPress(KeyEvent.VK_ALT);robot.keyPress(KeyEvent.VK_W);//释放Ctrl按键,像Ctrl,退格键,删除键这样的功能性按键,在按下后一定要释放robot.keyRelease(KeyEvent.VK_CONTROL);robot.keyRelease(KeyEvent.VK_ALT);// 该延迟不能少,否则无法搜索robot.delay(1000);}/*** 搜索好友** @param robot*/private static void startAddFrendOne(Robot robot, String friendNickName, boolean isFirst) {if (null == friendNickName || "".equals(friendNickName.trim())) {System.out.println("要搜索的好友信息不能为空");}if (isFirst) {// 第一次需要先点击添加好友按钮// 鼠标移动到添加好友位置-- 模拟点击添加好友按钮robot.mouseMove(mapPostion.get("添加好友按钮").get(0), mapPostion.get("添加好友按钮").get(1));point(mapPostion.get("添加好友按钮").get(0), mapPostion.get("添加好友按钮").get(1), robot);robot.delay(500);// 鼠标(按下/松开)事件,buttons可以填写 MouseEvent.BUTTON1_MASK 等robot.mousePress(MouseEvent.BUTTON1_MASK);robot.mouseRelease(MouseEvent.BUTTON1_MASK);robot.delay(500);} else {// 不是第一次需要清空之前搜索的好友clearFrinedSearchTxt(robot);}String Im = friendNickName;AutoIn(Im, mapPostion.get("输入内容搜索好友").get(0), mapPostion.get("输入内容搜索好友").get(1), robot);robot.delay(500);// 输入完毕后开始进行搜索robot.mouseMove(mapPostion.get("点击搜索好友").get(0), mapPostion.get("点击搜索好友").get(1));point(mapPostion.get("点击搜索好友").get(0), mapPostion.get("点击搜索好友").get(1), robot);robot.delay(500);// 鼠标(按下/松开)事件,buttons可以填写 MouseEvent.BUTTON1_MASK 等robot.mousePress(MouseEvent.BUTTON1_MASK);robot.mouseRelease(MouseEvent.BUTTON1_MASK);robot.delay(1000);}/*** 清除上一次搜索好友内容** @param robot*/private static void clearFrinedSearchTxt(Robot robot) {AutoClick(mapPostion.get("添加清除上一次搜索好友按钮").get(0), mapPostion.get("添加清除上一次搜索好友按钮").get(1), robot);}/*** 好友信息** @return*/private static Map<String, Object> getFriendMsg(Robot robot) {Map<String, Object> msgFriend = new HashMap<>(5);// 好友昵称位置robot.mouseMove(mapPostion.get("复制搜索好友的昵称位置").get(0), mapPostion.get("复制搜索好友的昵称位置").get(1));point(mapPostion.get("复制搜索好友的昵称位置").get(0), mapPostion.get("复制搜索好友的昵称位置").get(1), robot);robot.delay(500);// 鼠标右键点击robot.mousePress(MouseEvent.BUTTON3_MASK);robot.mouseRelease(MouseEvent.BUTTON3_MASK);robot.delay(500);robot.mouseMove(mapPostion.get("复制搜索好友的昵称复制位置").get(0), mapPostion.get("复制搜索好友的昵称复制位置").get(1));point(mapPostion.get("复制搜索好友的昵称复制位置").get(0), mapPostion.get("复制搜索好友的昵称复制位置").get(1), robot);robot.delay(500);AutoClick(mapPostion.get("复制搜索好友的昵称复制位置").get(0), mapPostion.get("复制搜索好友的昵称复制位置").get(1), robot);robot.delay(500);String nickName = printCtrlC();if ("".equals(nickName)) {msgFriend.put("hasFriend", false);return msgFriend;} else {msgFriend.put("hasFriend", true);msgFriend.put("昵称", nickName);}// 好友地区位置robot.mouseMove(mapPostion.get("复制搜索好友的地区位置").get(0), mapPostion.get("复制搜索好友的地区位置").get(1));point(mapPostion.get("复制搜索好友的地区位置").get(0), mapPostion.get("复制搜索好友的地区位置").get(1), robot);robot.delay(500);// 鼠标右键点击robot.mousePress(MouseEvent.BUTTON3_MASK);robot.mouseRelease(MouseEvent.BUTTON3_MASK);robot.delay(500);robot.mouseMove(mapPostion.get("复制搜索好友的地区复制位置").get(0), mapPostion.get("复制搜索好友的地区复制位置").get(1));point(mapPostion.get("复制搜索好友的地区复制位置").get(0), mapPostion.get("复制搜索好友的地区复制位置").get(1), robot);robot.delay(500);AutoClick(mapPostion.get("复制搜索好友的地区复制位置").get(0), mapPostion.get("复制搜索好友的地区复制位置").get(1), robot);robot.delay(500);String area = printCtrlC();if ("".equals(area)) {msgFriend.put("地区", "");} else {msgFriend.put("地区", area);}return msgFriend;}/*** 添加好友** @param robot*/private static Map<String, Object> addFriend(Robot robot) {Map<String, Object> msgFriend = new HashMap<>(5);// 点击添加通讯录robot.mouseMove(mapPostion.get("添加通讯录按钮").get(0), mapPostion.get("添加通讯录按钮").get(1));point(mapPostion.get("添加通讯录按钮").get(0), mapPostion.get("添加通讯录按钮").get(1), robot);robot.delay(500);// Thread.sleep(1* 1000); // 休眠 1 秒// 鼠标(按下/松开)事件,buttons可以填写 MouseEvent.BUTTON1_MASK 等robot.mousePress(MouseEvent.BUTTON1_MASK);
//        robot.delay(1000);robot.mouseRelease(MouseEvent.BUTTON1_MASK);robot.delay(500);// 设置申请的信息 我是xxxString myApplyMsg = mapMyMsg.get("添加朋友申请信息");AutoIm(myApplyMsg, mapPostion.get("填写发送添加朋友申请").get(0), mapPostion.get("填写发送添加朋友申请").get(1), robot);msgFriend.put("设置申请的信息", myApplyMsg);// 设置备注名称String friendRemark = mapMyMsg.get("添加朋友备注信息");AutoIm(friendRemark, mapPostion.get("填写备注名").get(0), mapPostion.get("填写备注名").get(1), robot);msgFriend.put("设置备注名称", friendRemark);// 设置标签String friendTag = mapMyMsg.get("添加朋友标签信息");AutoIm(friendTag, mapPostion.get("填写标签").get(0), mapPostion.get("填写标签").get(1), robot);msgFriend.put("设置标签", friendTag);// 确定添加// AutoClick(mapPostion.get("确定添加好友").get(0), mapPostion.get("确定添加好友").get(1), robot);// 取消AutoClick(mapPostion.get("取消添加好友").get(0), mapPostion.get("取消添加好友").get(1), robot);return msgFriend;}/*** 键盘赋值的内容** @return*/public static String printCtrlC() {Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();DataFlavor flavor = DataFlavor.stringFlavor;if (clip.isDataFlavorAvailable(flavor)) {try {String s = (String) clip.getData(flavor);return s;} catch (Exception e) {e.printStackTrace();}}return "";}/*** 函数的目的是确定鼠标的坐标,不然鼠标的坐标老对不上* 1、输入的值(鼠标想去的坐标)* 2、循环判断。当前的鼠标的坐标和想要去的坐标的区别,如果当前坐标和想去的绝对值小于等2,就退出去。** @param x* @param y* @throws InterruptedException*/private static void point(int x, int y, Robot robot) {robot.mouseMove(x, y);Point point = MouseInfo.getPointerInfo().getLocation();while (Math.abs(x - point.getX()) > 2 || Math.abs(y - point.getY()) > 2) {robot.mouseMove(x, y);point = MouseInfo.getPointerInfo().getLocation();}}private static void AutoIn(String Im, int x, int y, Robot robot) {point(x, y, robot);//使鼠标位置定位到对应位置上// 鼠标(按下/松开)事件,buttons可以填写 MouseEvent.BUTTON1_MASK 等robot.mousePress(MouseEvent.BUTTON1_MASK);robot.mouseRelease(MouseEvent.BUTTON1_MASK);// 将我是xxx发送到剪切板Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();Transferable tText = new StringSelection(Im);clip.setContents(tText, null);// 以下两行按下了ctrl+v,完成粘贴功能robot.keyPress(KeyEvent.VK_CONTROL);robot.keyPress(KeyEvent.VK_V);robot.keyRelease(KeyEvent.VK_CONTROL);robot.delay(1000);clip.setContents( new StringSelection(""), null);}/*** 点击** @param x* @param y* @param robot* @throws InterruptedException*/private static void AutoClick(int x, int y, Robot robot) {robot.mouseMove(x, y);point(x, y, robot);robot.delay(500);// 鼠标(按下/松开)事件,buttons可以填写 MouseEvent.BUTTON1_MASK 等robot.mousePress(MouseEvent.BUTTON1_MASK);robot.mouseRelease(MouseEvent.BUTTON1_MASK);robot.delay(500);}/*** 添加好友之我是xxx* 1、先把之前的删除了* 2、剪切板里获取自己输入的** @return*/private static void AutoIm(String Im, int x, int y, Robot robot) {point(x, y, robot);//使鼠标位置定位到对应位置上// 鼠标(按下/松开)事件,buttons可以填写 MouseEvent.BUTTON1_MASK 等robot.mousePress(MouseEvent.BUTTON1_MASK);robot.mouseRelease(MouseEvent.BUTTON1_MASK);//先清除自带的(最多20次)for (int i = 0; i < 20; i++) {robot.keyPress(KeyEvent.VK_BACK_SPACE);robot.delay(100);robot.keyRelease(KeyEvent.VK_BACK_SPACE);}// 将我是xxx发送到剪切板Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();Transferable tText = new StringSelection(Im);clip.setContents(tText, null);// 以下两行按下了ctrl+v,完成粘贴功能robot.keyPress(KeyEvent.VK_CONTROL);robot.keyPress(KeyEvent.VK_V);robot.keyRelease(KeyEvent.VK_CONTROL);robot.delay(1000);clip.setContents( new StringSelection(""), null);}//获取Robotprivate static Robot getRobot() {// 创建Robot对象Robot robot = null;try {robot = new Robot();} catch (AWTException e) {e.printStackTrace();}return robot;}
}

1.2 好友信息 FriendBaseDto:

package org.example.wechat.dto;import lombok.Data;/*** @Description TODO* @Date 2023/2/3 14:40* @Author lgx* @Version 1.0*/
@Data
public class FriendBaseDto {// 要搜索的好友号private String  friendSearch;// 改好友号是否搜到了好友private boolean  hasFriend = false;// 好友的昵称信息private String  nickName;// 好友的地区信息private String  area;// 申请添加好友是申请信息private String  applyMsg;// 好友的备注private String  friendRemark;// 好友的标签private String  friendLabel;// 搜索添加过程产生的异常信息private String  errorMsg;
}

1.3 好友原始文件枚举:FriendSourceTypeEnum

package org.example.wechat.enums;import lombok.AllArgsConstructor;
import lombok.Getter;/*** @Description TODO* @Date 2023/2/3 15:41* @Author lgx* @Version 1.0*/
@Getter
@AllArgsConstructor
public enum  FriendSourceTypeEnum {从txt导入 (1, "从txt导入"),从docx导入 (2, "从docx导入"),从excel导入 (3, "从excel导入"),自定义 (4, "自定义"),;private Integer type;private String typeName;}

1.4 结果:
搜索的文件信息示例:

搜索的结果信息示例:

2 微信元素位置的获取:
使用 ctrl+alt+a 使用微信的截图工具,:

3 总结:
3.1 本位使用robot 通过在微信界面对应位置点击和输入信息完成微信好友的模拟添加,当微信界面移动时,需要重新获取到每个元素具体的位置;
3.2 微信批量添加好友会有限制,当短时间内在微信中大量添加微信好友,会被微信提示 搜索过于频繁,稍后重试;

JAVA工具篇--java.awt.Robot模拟微信批量添加好友相关推荐

  1. Java提高篇 —— Java三大特性之继承

    一.前言 在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事 ...

  2. Java基础篇--Java 数组

    Java基础篇--Java 数组 Java 数组 声明数组变量 创建数组 处理数组 For-Each 循环 数组作为函数的参数 数组作为函数的返回值 多维数组 多维数组的动态初始化(以二维数组为例) ...

  3. 如何实现微信批量添加好友

    微信批量添加好友的方法有很多种,常见的有以下几种: 使用第三方软件,如"微信助手","微信自动添加好友"等. 使用手机模拟器,如"蓝牙模拟器" ...

  4. Java提高篇——Java实现多重继承

    多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承.有些时候我们会认为如果系统中需要使用多重继承往往都是糟糕的设计,这个时候我们往往需 ...

  5. Java IO篇 Java IO编程

    Java IO 一.java io 概述 1.1 相关概念 二.Java IO类库的框架 2.1 Java IO的类型 2.2 IO 类库 三.Java IO的基本用法 3.1 Java IO :字节 ...

  6. Java提高篇——Java中的异常处理

    对于运行时异常.错误和检查异常,Java技术所要求的异常处理方式有所不同. 由于运行时异常及其子类的不可查性,为了更合理.更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出, ...

  7. 企业微信批量添加好友

    企业微信成官方唯一合规私域流量搭建平台,在企业微信推出的同时,腾讯官方也进行了一系列的举措,雷厉风行地整顿.打击微信个人号工具,一旦发现个人号借助外挂工具进行批量添加好友等违规行为,都会进行封号.账户 ...

  8. java工具类-java仿微信九宫格头像

    创建Utils类 ImageUtil package com.mrd.utils;import javax.imageio.ImageIO; import java.awt.Color; import ...

  9. java里utils写什么_工具篇-Java中一些utils

    下边是整理的一些Java开发的utils,顺便吐槽下新浪博客的编辑器排版跟我写的博客一样 烂,所以采用的博客园 字符串 1.Java中String与其他类型之间的转换 String与日期对象 1 pu ...

最新文章

  1. 不是python对文件的读操作方法的是-python的文件操作方法
  2. ASP.NET MVC (五、HttpClient接口解析)
  3. RabbitMQ—AMQP协议重要概念介绍
  4. 总结-各种安全漏洞学习环境集合(转)
  5. Reuse library debug in Chrome - phase2 handle success response (2)
  6. 正确使用 Volatile 变量
  7. java栈的应用_Java堆栈应用程序
  8. Codeforces 52C
  9. html5开发桌面程序调用dll,使用Visual Studio开发Html5应用
  10. flowable 配置自定义表单_web工作流管理系统开发之四 自定义表单
  11. luogu P4234 最小差值生成树
  12. 数据宝贝儿放云上,你放心么?
  13. uniapp打包之后首页白屏
  14. 闪付卡(QuickPass)隐私泄露原理
  15. 一个可以提升180%推广效果的信息流广告投放策略
  16. mysql mdf ldf_mdf和ldf是什么文件
  17. UNICODE、GB18030、ASCII编码
  18. html网页文字链接的若干问题
  19. 微信网页jssdk使用
  20. SpringBoot——日志文件

热门文章

  1. vim cscope java_【转】Cscope的使用(领略Vim + Cscope的强大魅力)
  2. JVAV——网络编程UDP/TCP
  3. 系统思考:啤酒游戏反思的主要内容是什么?
  4. 封装型号对照_多图预警,17种元器件PCB封装图鉴
  5. 2023全国特种作业操作证钎焊模拟考试试卷一[安考星]
  6. python爬取知乎文章_Python爬取知乎日报,推送到kindle
  7. 什么是人因学( Ergonomics)?
  8. CSDN文章:提示请设置内容等级
  9. CSS------伪类(:first)和伪元素(::after)汇总以及区别分析
  10. 华为g9显示无服务器,华为手机连不上电脑_华为p9手机连不上电脑