最新手机QQ频道私信营销群发技术的实现
手机QQ频道是一个腾讯最近两年发布的一个新功能,很多人还不知道,不摘掉的,可以自行百度。自我的感觉,手机QQ是一个类似于QQ群差不多的,里面也是聚集了很多想同主题相同爱好的网友。市面上针对手机QQ群做营销的工具倒是挺多,针对手机QQ频道营销的还没看到过,刚好有朋友要做手机QQ频道私信自动发的功能,听说引流效果不错。找了一圈,没发现有可供参考的代码,只能自已想办法了。经过近半个月的修修改改,终于初见成效,可以稳定的运行。
首先,这个营销工具达到的目标很简单,就是可以对在QQ频道的所有人一对一的发私信,不能重复发送。因为手机QQ频道发送完一个私信后,返回时,并不会返回到QQ相关的频道列表里,不能一条一条的发送,得再重新进入频道,再选定人员,再发送,和PC版不一样,所以得记录下已发送的频道与发送完的人员ID.所以要分为两个重要步骤
一.收集QQ频道与QQ频道里的所有成员ID.
二.收集完后,再进行发送的动作。
完成后的效果如下:上传bilibili没通过,只能截图了

主要思路:利用auto.js做自动脚本。运行环境,雷电模拟器,安卓7.1版本,数据库sqlserver,做api接口用于数据交互。
数据库:sqlserver
接口开发:c#
脚本:auto.js
开发工具:Visual Studio Code
看似一个小小的工具,涉及的技术还是不少的。auto.js我也是现学现卖。开发环境,如何配置可以参考网上的教程,这里我就不写了。
主要分为以下几个步骤
1.数据库设计
很简单,就是记录下关键的信息,把采集下来的QQ频道信息放在数据库,用于存取。
2.接口开发
与脚本动作与数据交互
3.脚本开发
3.1 用于采集QQ频道信息,上代码
auto.waitFor();
// 启动QQ
// 启动QQ应用程序
app.launch("com.tencent.mobileqq");
waitForPackage("com.tencent.mobileqq",10000);
// 等待QQ启动
toastLog("等待QQ启动完毕");
//获得Q号
var publicfunction = require('publicfunction.js');
var Base64 = require('BASE64.js');
click(106,1552);//点下消息
sleep(2000);
var qqid=publicfunction.qqidtoupdatelocaip();//是到当前局域网IP
if (qqid==null)
{
sleep(1000);
id("ivTitleBtnLeft").findOne().click();
sleep(2000);
id("nu0").findOne().click();
sleep(2000);
qqid=publicfunction.findqqid();
}
log("QQ号:"+qqid);
var qqpindaobtn=id("kbi").className("android.widget.TextView").text("频道").findOne().parent();
if (qqpindaobtn!=null)
{
let bounds = qqpindaobtn.bounds();
click(bounds.centerX(), bounds.centerY());
sleep(2000);
}
else
{
log("没有");
}
// click(273,1556);//点QQ频道
// 有这个频道
var qqpindaoobj=id("kbi").className("android.widget.TextView").text("频道").findOne();
if (qqpindaoobj!=null)
{
if (qqpindaoobj.text()=="频道")
{
log("有这个频道");
}
}
sleep(1000);
//--------------------------------------------------------
swipe(56,578,24,1339,2000); //滑动到最上面
var curri=0;
for(var currloop=1;currloop<=2;currloop++)
{
left_click();
}
exit();
function left_click()//点左边的导航栏目
{
var count8=list.childCount();
for(var maini = 1; maini < count8; maini++)
{
if (maini==10)
{
log("向下滑动到底");
swipe(24,1339,56,578,2000);
}
var child = list.child(maini);
if (child!=null)
{
toastLog("第"+maini+"次");
child.click();//点左面的栏目
sleep(2000);
var u7y=id("u7y").findOne(3000);
if (u7y!=null)
{
log(u7y.text());
}
else
{
if(id("pcl").exists())
{
log("搜索");
continue;
}
sleep(15000);
continue;
}
var pindaoidstr;//qq频道id
var oq3=id("oq3").findOne(5000);//成员列表
if (oq3!=null)
{
let bounds = oq3.bounds();
click(bounds.centerX(), bounds.centerY());
sleep(1000);
id("pfh").waitFor();
//频道号
if (id("pfh").findOne()!=null)
{
log(id("pfh").findOne().text());
//插入到数据库
pindaoidstr=id("pfh").findOne().text().replace('频道号:','');
//判断下频道号还在不
var bool_value=publicfunction.qqpindaomainisexits(pindaoidstr,qqid);
log(bool_value);
if (bool_value=="false")
{
publicfunction.qqpindao_insert_qqpindaomain(qqid,pindaoidstr,u7y.text());
}
else
{
log("已经有这个频道的数据了")
click(429,237);
sleep(1000);
continue;//退出当前
}
}
id("pfr").waitFor();
id("pfr").click();//点成员列表
sleep(5000);
//找详细信息
find_detailInfo(pindaoidstr);
}
// break;//是否循环
}
}
}
3.2 收集完成后,就是发送私信
```javascript
auto.waitFor();
// 启动QQ
// 启动QQ应用程序
app.launch("com.tencent.mobileqq");
waitForPackage("com.tencent.mobileqq",10000);
toastLog("等待QQ启动完毕");
var publicfunction = require('publicfunction.js');
var Base64 = require('BASE64.js');
click(106,1552);//点下消息
sleep(2000);
var qqid=publicfunction.qqidtoupdatelocaip();
if (qqid==null)
{
sleep(1000);
id("ivTitleBtnLeft").findOne().click();
sleep(2000);
id("nu0").findOne().click();
sleep(2000);
qqid=publicfunction.findqqid();
}
log("QQ号:"+qqid);
var sendcontent=publicfunction.getrandomcontent(qqid);
if (sendcontent==null)
{
sendcontent=publicfunction.getrandomcontent(qqid);
}
log("发送内容:"+sendcontent);
startQQpindao_sendinfo();
function randomsleep()
{
// let number = Math.random(2,8);
let number = randomsleep2(2,8);
sleep(number*1000);
}
function randomsleep2(min,max)
{
let number = Math.floor(Math.random() * (max - min + 1) + min);
sleep(number*1000);
}
3.3 用到的调用接口的方法 publicfunction.js
importClass("java.net.InetAddress");
importClass("java.net.NetworkInterface");
importClass("java.net.Inet6Address");
var publicfunction={}
publicfunction.getIntranetIP=function getIntranetIP() {
// 获取内网IP地址
let networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
let networkInterface = networkInterfaces.nextElement();
let inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
let inetAddress = inetAddresses.nextElement();
if (inetAddress instanceof Inet6Address) {
continue;
}
let ip = inetAddress.getHostAddress();
// log(ip);
if (!"127.0.0.1".equals(ip)) {
return inetAddress.getHostAddress();
}
}
}
}
3.4 BASE64.js
var Base64 = {
// private property
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode: function(input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode: function(input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode: function(string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode: function(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if ((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i + 1);
c3 = utftext.charCodeAt(i + 2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}
module.exports = Base64;
还有数据库结构与接口就贴了,很简单,这样的一套下来,运行还是比较稳定的。手机QQ版本是v88907975,雷电的设置看图
需要全套解决方案的私信我,不定时在线。