Appium自动微信读书打卡
1.需求分析
1.1需求
本研究目的是实现在手机上自动完成读书打卡功能。
1.2分析
实现微信读书打卡项目,分为两部分,第一部分是实现微信读书,第二部分是实现打卡。微信读书部分需要先找到需要阅读的书籍,然后滑动书籍,最后对获取书籍右下角的页码。打卡部分需要先搜索到微信群聊,然后复制页码信息,最后把页码发送到指定的群里。
2.设计
从需求分析中,可总结出需要设计实现以下三种功能
功能1需要能够连接并能够启动移动端app的工具帮助实现自动化
功能2微信读书识别打卡页码内容
功能3打卡页码文本内容发送到微信打卡群
功能1的设计实现,可采用appium框架工具实现app自动化;
功能2的设计实现,可归纳为以下几点
1)启动微信读书app。在app中找到需要打卡的书籍,定时翻页查看书籍,记录书籍开始阅读到结束阅读时的起止页码。
其中找到需要阅读的书籍以及翻页可借助appium实现,对于记录页码,需要做出讨论。如果页码内容属于文本内容,通过appium定位工具可读取到页码;如果页码部分属于非文本内容,则采用生成页码部分图片,然后图片内容识别文本技术识别页码内容。(经过实践,app中页码部分为非文本内容,页码图片使用appium框架截图API生成,页码图片内容识别技术使用Tesseract-OCR软件识别),以上描述设计实现读取打卡的页码功能思路。
2)打卡页码发送到微信群。启动并登录微信,找到需要打卡的群聊,将打卡内容(微信读书已阅读到的页码)通过群聊输入框发送至微信群,完成打卡功能
3.实现
项目分为微信读书和打卡两部分实现。
3.1微信读书
3.1.1说明
先打开微信读书,点击书架[书架ID]按钮,找到指定的书籍[书籍ID]点击,设置固定时间间隔向左滑动屏幕,设置一段时间读取书籍右下角的页码。
3.1.2步骤
1)找到书籍
点击书架[书架ID]按钮,找到指定的书籍[书籍ID]点击。
// 定位书架位置 String book_id = "com.tencent.weread:id/rx"; driver.findElementById(book_id).click(); Thread.sleep(1000); // waiTime(500, driver); // 点开所需要的书籍 String book_xpath = "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/androidx.viewpager.widget.ViewPager/android.widget.FrameLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.FrameLayout/androidx.recyclerview.widget.RecyclerView/android.widget.RelativeLayout[8]/android.widget.RelativeLayout/android.view.View[2]"; driver.findElementByXPath(book_xpath).click();
2)滑动书籍
//向左滑动 public static void swipeToLeft(AndroidDriver driver) { int width = driver.manage().window().getSize().width;// 获取当前屏幕的宽度 int height = driver.manage().window().getSize().height;// 获取当前屏幕的高 TouchAction touchAction = new TouchAction(driver); //new一个TouchAction对象,调用其按压press()方法,输入坐标点,moveTo移动到下一个坐标点,之后调用release()和perform()方法执行 PointOption startOption = PointOption.point(width * 4 / 5, height / 2); PointOption endOption = PointOption.point(width / 5, height / 2); //向左边滑动100ms WaitOptions waitOption = WaitOptions.waitOptions(Duration.ofMillis(100));// 设置动作持续时间:按压一秒 touchAction.press(startOption).waitAction(waitOption).moveTo(endOption).release().perform();// 按压一秒——移动——松开释放 }
3)定时
这里定时是指两个定时,第一个是阅读的书籍应该每隔多长时间滑动一次,第二个定时是每次固定多长时间结束阅读。我测试了我大概阅读一页的速度是40s(我手机中的微信读书的字体设置的是20),所以我设置每隔40s滑动一次屏幕。设置每隔40s滑动一次屏幕,一共滑动30页。
// 滑动书籍 int k = 0; while (k < 1) { Thread.sleep(24000); swipeToLeft(driver); k++; }
4)截图
/** * 截图 */ public static String captureApp(AndroidDriver driver) { System.out.println("开始截图"); // 截图名称 String screenshotName = getCurrentDateTime() + "wechat_book.png"; String filePath = SCREENSHOT_PATH + File.separator + screenshotName; // 截图目录 File screenshotFile = new File(SCREENSHOT_PATH); // 若文件夹不存在就创建该文件夹 if (!screenshotFile.exists() && !screenshotFile.isDirectory()) { screenshotFile.mkdirs(); } try { // 截图操作 File sourceFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); // 截图存储 FileUtils.copyFile(sourceFile, new File(filePath)); } catch (IOException e) { e.printStackTrace(); System.out.println("截图操作异常!"); } System.out.println("截图结束"); return filePath; }
5)识别页码
public static void getSubImg(String soursePicPath, String targetPath) { File sourcePic = new File(soursePicPath); try { BufferedImage pic1 = ImageIO.read(sourcePic); int width = pic1.getWidth(); int height = pic1.getHeight(); // 参数依次为,截取起点的x坐标,y坐标,截取宽度,截取高度 BufferedImage pic2 = pic1.getSubimage(width / 9 * 7, height / 16 * 15, width / 9 * 2, height / 16 * 1); // 将截取的子图另行存储 File desImage = new File(targetPath); ImageIO.write(pic2, "png", desImage); } catch (IOException e1) { e1.printStackTrace(); } }
3.1.3结果
实现微信读书并获取书籍页码。
3.2打卡
3.2.1说明
打开微信,找到搜索按钮的ID,找到搜索框第一条结果,取文本框ID并输入文字,点击确定按钮,即找到确定按钮ID。
3.2.2步骤
1)向微信发送消息
设置Appium可以输入中文
//设置appium可以输入中文 capabilities.setCapability("unicodeKeyboard", "true");
2)打开微信
// 获取微信driver public static AndroidDriver getWechatDriver() throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); // 模拟器类型 // capabilities.setCapability("deviceName", "Android Emulator"); capabilities.setCapability("deviceName", "device"); // 自动化测试引擎 capabilities.setCapability("automationName", "Appium"); // 手机操作系统Android capabilities.setCapability("platformName", "Android"); // 手机操作系统版本号 capabilities.setCapability("platformVersion", "7.1.2"); // app包名 capabilities.setCapability("appPackage", "com.tencent.mm"); // app中启动的 Activity名称 capabilities.setCapability("appActivity", ".ui.LauncherUI"); capabilities.setCapability("automationName", "uiautomator2"); // noReset设置 capabilities.setCapability("noReset", "true"); // 设置appium可以输入中文 capabilities.setCapability("unicodeKeyboard", "true"); AndroidDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); return driver; }
3)完成打卡
public static void showTime(String pageNum) throws Exception {
// 获得微信driver
AndroidDriver driver = getWechatDriver();
// 微信首页启动大概6s
Thread.sleep(10000);
// 打开微信kyt
// String wx_xpath = "//android.widget.TextView[@content-desc=\"微信\"]";
// driver.findElementByXPath(wx_xpath).click();
// Thread.sleep(1000);
// 找到搜索按钮的ID
String wx_find = "com.tencent.mm:id/he6";
driver.findElementById(wx_find).click();
Thread.sleep(1000);
// 取文本框ID并输入文字
String wx_group = "com.tencent.mm:id/bxz";
driver.findElementById(wx_group).sendKeys("小窝窝");
Thread.sleep(1000);
// 找到搜索框第一条结果
String group_loaction = "com.tencent.mm:id/ir3";
driver.findElementById(group_loaction).click();
Thread.sleep(1000);
// 输入读书的名称和页码
String sendmassage = "com.tencent.mm:id/auj";
driver.findElementById(sendmassage).sendKeys("名人名言书屏" + pageNum);
Thread.sleep(1000);
// 点击确定按钮,即找到确定按钮ID
String sendbutton = "com.tencent.mm:id/ay5";
driver.findElementById(sendbutton).click();
driver.closeApp();
driver.quit();
}
3.2.3实现
实现效果如下图所示,微信读书在微信上打卡成功。
4.断网测试
把网断开进行测试,看是否还可以打卡成功,测试表明,当没有网的时候,是无法获取书的页码,虽然最后可以打卡,但是打卡没有页码,并且打卡消息也是无法发出的。
5.PSP