├── .gitignore
├── README.md
├── features
├── feature1.feature
├── step_definitions
│ ├── definitions1.js
│ ├── model1.tmodel
│ └── model1_files
│ │ ├── Window.png
│ │ └── 文本编辑器.png
└── support
│ └── env.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 微信发送自动暖信息
2 |
3 |
4 | ## 前言
5 |
6 | > 每个都是为公司的应用写自动化测试脚本,没曾把这些自动化应用到生活中,直到逛社区看到 [用Node+wechaty写一个爬虫脚本每天定时给女(男)朋友发微信暖心话](https://juejin.im/post/5c77c6bef265da2de6611cff) 发现还有如此好玩的事情。于是赏玩了一把,觉得还可以有更美好的实现方式。
7 |
8 |
9 | 上面的脚本还要进行扫码登录的操作,对于经常写自动化脚本的我们最好是一劳永逸的。所以这次我的脚本:只需一次登录。😁
10 |
11 | 下面言归正传
12 |
13 |
14 | ## 准备
15 |
16 | * 一台Windows操作系统。
17 | * 在Windows上安装微信客户端。
18 | * 在Windows上安装[CukeTest](http://cuketest.com)
19 |
20 | 这里说明一下为啥我要用CukeTest?
21 |
22 | > 因为CukeTest是一款专门用来做自动化测试的工具,我经常用它来开发Windows,Web,Mobile,Api等自动化测试脚本。 本次我主要是想用它来自动化操作Windows版微信,你在Windows上登录微信后,不用管它,它会一直在线,只要不管电脑,微信可以随时在线,再也不用担心掉线了。
23 |
24 |
25 | Pc上安装好微信客户端,我们手动登录一下,为了方便快速的让自动化脚本找到你的哪个她(或他),可以事先把她(或他)的微信置顶。
26 |
27 |
28 | ## 暖心内容来源
29 |
30 | 和上面的大佬一样也是每日一句来自[one](http://wufazhuce.com/)
31 |
32 | 天气信息来自[墨迹天气](http://tianqi.moji.com/)
33 |
34 |
35 | ## 使用库
36 |
37 | * [chromedriver](https://www.npmjs.com/package/chromedriver)
38 | * [selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver)
39 | * [moment](https://www.npmjs.com/package/moment)
40 |
41 | 这些库大家如果经常写自动化测试,应该很熟悉。chromedriver chrome浏览器的驱动, selenium-webdriver web自动化库。
我脚本的原理比较简单,就是把平时我们手工操作的步骤转化为自动化脚本,自动打开chrome浏览器,去one和墨迹天气页面上提取信息。
因为CukeTest内置的有对Windows控件的操作,用CukeTest直接去自动操作微信,把上面提取出来的信息发送出去即可。
42 |
43 |
44 | ## 运行
45 |
46 | ```
47 | git clone
48 | cd auto_wechat
49 | npm install
50 | ```
51 |
52 | 使用CukeTest 打开项目,点击运行就可以看到运行效果。
53 |
54 | ####
55 |
56 | ## 主要代码片段
57 |
58 | ### 1.编辑一个故事场景
59 |
60 | 
61 |
62 |
63 | ### 2.获取信息
64 | 获取One
65 |
66 | ```javascript
67 | await driver.get(url);
68 | let css_selector = '.fp-one-cita-wrapper>.fp-one-cita > a'; //元素定位
69 | let text = await driver.findElement({css:css_selector}).getText();
70 | this.oneText = text;
71 | ```
72 | 获取天气
73 |
74 | ```javascript
75 | await driver.get(url);
76 | let current_tm = await driver.findElement({ css:'div.wea_weather.clearfix > em'}).getText();
77 | let current_state = await driver.findElement({ css:'.wea_weather.clearfix > b'}).getText();
78 | let wea_tips = await driver.findElement({ css:'.wea_tips.clearfix > em'}).getText();
79 | let current_about = await driver.findElement({ css:'.wea_about.clearfix'}).getText();
80 | this.today_wea = `
81 | 温度:${current_tm}°
82 | 天气:${current_state}
83 | ${current_about}
84 | ${wea_tips}
85 | `
86 | });
87 | ```
88 |
89 | ### 3.微信界面操作
90 | 操作微信界面需要在CukeTest中添加虚拟控件。
91 | 
92 |
93 | 添加完虚拟控件,调用CukeTest提供的API即可。模型管理器中可以看到。
94 | 
95 |
96 | 复制或拖拽相关的方法到代码编辑器中即可。
97 |
98 |
99 | ### 4.运行
100 |
101 | 
102 |
--------------------------------------------------------------------------------
/features/feature1.feature:
--------------------------------------------------------------------------------
1 | # language: zh-CN
2 | 功能: 自动发送微信消息
3 | 你可以选择给爱人,亲戚,朋友等等发送贴心的天气预报信息或者每日一言信息
4 |
5 | 场景: 微信贴心助手
6 | 假如打开浏览器从"http://wufazhuce.com/"找到当日一句
7 | 同时从"http://tianqi.moji.com/weather/china/shanghai/shanghai"获取当天的天气
8 | 那么保存这些信息并关闭浏览器
9 | 当自动打开微信
10 | 同时找到你特别关心的人
11 | 那么就让脚本把这些信息自动发送给你关心的人吧
--------------------------------------------------------------------------------
/features/step_definitions/definitions1.js:
--------------------------------------------------------------------------------
1 | const { Given, When, Then } = require('cucumber');
2 | const { TestModel, Auto } = require('leanpro.win');
3 | const { Util } = require('leanpro.common');
4 | require('chromedriver')
5 | let {Builder} = require('selenium-webdriver');
6 | let moment = require('moment')
7 |
8 | let model = TestModel.loadModel(__dirname + "/model1.tmodel");
9 | let driver = new Builder().forBrowser('chrome').build();
10 |
11 | //// 你的步骤定义 /////
12 |
13 |
14 |
15 | Given(/^自动打开微信$/, async function () {
16 |
17 | await model.getVirtual("msg").click(0, 0, 1);
18 | await model.getWindow("Window").activate();
19 |
20 |
21 | });
22 |
23 | Given(/^找到你特别关心的人$/, async function () {
24 |
25 | await model.getVirtual("user").click(0, 0, 1);
26 |
27 | });
28 |
29 |
30 |
31 | Given(/^从"([^"]*)"获取当天的天气$/, async function (url) {
32 |
33 | await driver.get(url);
34 | let current_tm = await driver.findElement({ css:'div.wea_weather.clearfix > em'}).getText();
35 | let current_state = await driver.findElement({ css:'.wea_weather.clearfix > b'}).getText();
36 | let wea_tips = await driver.findElement({ css:'.wea_tips.clearfix > em'}).getText();
37 | let current_about = await driver.findElement({ css:'.wea_about.clearfix'}).getText();
38 | this.today_wea = `
39 | 温度:${current_tm}°
40 | 天气:${current_state}
41 | ${current_about}
42 | ${wea_tips}
43 | `
44 | });
45 |
46 | Then(/^就让脚本把这些信息自动发送给你关心的人吧$/, async function () {
47 | let today = moment().format('YYYY-MM-DD ');
48 | let current_time = moment().format('YYYY MM DD HH:mm:ss ')
49 | let d = moment().toArray()
50 | d = d.slice(0, 3)
51 | let d_arr = moment(d);
52 | let day = moment([2016,3,5]);
53 | let days = d_arr.diff(day,'days')
54 | let content =
55 | `今天是${today}
56 | ❤
57 | ${this.oneText}
58 | ❤
59 | 今天上海天气:
60 | ${this.today_wea}
61 | --:) 来自微信贴心助手 ${current_time}
62 | `
63 | let proc = Util.launchProcess("notepad");
64 | await model.getDocument("文本编辑器").set(content);
65 | await model.getDocument("文本编辑器").click();
66 | await model.getDocument("文本编辑器").pressKeys("^a");
67 | await Util.delay(1000);
68 | await model.getDocument("文本编辑器").pressKeys("^c");
69 | Util.stopProcess(proc);
70 |
71 | await model.getWindow("Window").activate();
72 | await model.getVirtual("editmsg").click(0, 0, 1);
73 | await model.getVirtual("editmsg").click(10, 10, 2);
74 | await Util.delay(1000);
75 | await model.getVirtual("editmsg").click(15, 15, 1);
76 | await Util.delay(1000);
77 | await model.getVirtual("send").click(0, 0, 1);
78 |
79 | });
80 |
81 | Given(/^打开浏览器从"([^"]*)"找到当日一句$/, async function (url) {
82 |
83 | await driver.get(url);
84 | let css_selector = '.fp-one-cita-wrapper>.fp-one-cita > a';
85 | let text = await driver.findElement({css:css_selector}).getText();
86 | this.oneText = text;
87 | });
88 |
89 | Then(/^保存这些信息并关闭浏览器$/, async function () {
90 |
91 | await driver.quit();
92 | });
93 |
94 |
--------------------------------------------------------------------------------
/features/step_definitions/model1.tmodel:
--------------------------------------------------------------------------------
1 | {
2 | "ntype": "app",
3 | "process": null,
4 | "controls": [
5 | {
6 | "ntype": "uia",
7 | "nname": "Window",
8 | "description": "",
9 | "identifyProperties": {
10 | "type": "Window",
11 | "className": "WeChatMainWndForPC",
12 | "title": "微信"
13 | },
14 | "cachedProperties": {
15 | "type": "Window",
16 | "className": "WeChatMainWndForPC",
17 | "title": "微信",
18 | "boundingRectangle": "345,166,782,534"
19 | },
20 | "image": {
21 | "imgPath": "Window.png",
22 | "rect": "1,1,782,534"
23 | },
24 | "children": [
25 | {
26 | "ntype": "virtual",
27 | "nname": "msg",
28 | "description": "",
29 | "identifyProperties": {
30 | "boundingRectangle": "2,64,55,48",
31 | "align": "0"
32 | }
33 | },
34 | {
35 | "ntype": "virtual",
36 | "nname": "user",
37 | "description": "",
38 | "identifyProperties": {
39 | "boundingRectangle": "61,62,245,60",
40 | "align": "0"
41 | }
42 | },
43 | {
44 | "ntype": "virtual",
45 | "nname": "editmsg",
46 | "description": "",
47 | "identifyProperties": {
48 | "boundingRectangle": "0,37,469,72",
49 | "align": "3"
50 | }
51 | },
52 | {
53 | "ntype": "virtual",
54 | "nname": "send",
55 | "description": "",
56 | "identifyProperties": {
57 | "boundingRectangle": "678,497,76,27",
58 | "align": "0"
59 | }
60 | }
61 | ]
62 | },
63 | {
64 | "ntype": "uia",
65 | "nname": "Window1",
66 | "description": "",
67 | "identifyProperties": {
68 | "type": "Window",
69 | "className": "Notepad"
70 | },
71 | "cachedProperties": {
72 | "type": "Window",
73 | "className": "Notepad",
74 | "title": "无标题 - 记事本",
75 | "boundingRectangle": "378,192,658,524"
76 | },
77 | "children": [
78 | {
79 | "ntype": "uia",
80 | "nname": "文本编辑器",
81 | "description": "",
82 | "identifyProperties": {
83 | "type": "Document",
84 | "automationId": "15"
85 | },
86 | "cachedProperties": {
87 | "automationId": "15",
88 | "type": "Document",
89 | "className": "Edit",
90 | "name": "文本编辑器",
91 | "boundingRectangle": "386,243,642,465"
92 | },
93 | "image": {
94 | "imgPath": "文本编辑器.png",
95 | "rect": "1,1,642,465"
96 | }
97 | }
98 | ]
99 | }
100 | ]
101 | }
--------------------------------------------------------------------------------
/features/step_definitions/model1_files/Window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/autonodejs/auto_wechat/6605afd1248b1c9a954002f3a18abdbbe1aea009/features/step_definitions/model1_files/Window.png
--------------------------------------------------------------------------------
/features/step_definitions/model1_files/文本编辑器.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/autonodejs/auto_wechat/6605afd1248b1c9a954002f3a18abdbbe1aea009/features/step_definitions/model1_files/文本编辑器.png
--------------------------------------------------------------------------------
/features/support/env.js:
--------------------------------------------------------------------------------
1 | let { setDefaultTimeout } = require('cucumber');
2 |
3 | setDefaultTimeout(30 * 1000); //set step timeout to be 30 seconds
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wechat",
3 | "version": "1.0.0",
4 | "description": "generated by CukeTest, LeanPro Co., Ltd",
5 | "main": "",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "chromedriver": "^2.46.0",
13 | "moment": "^2.24.0",
14 | "selenium-webdriver": "^4.0.0-alpha.1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------