需求
其实需求只是让定期刷新微博的特别关注页面,当有关注人发文章时,能快速回复,后来想想,干脆自动登陆也做进去。省的还要过多讲解怎么操作。
分析
从需求来看,是线性逻辑,分两部分:
微博登陆
- 打开微博登陆界面
- 输入账户密码
- 点击登陆
- 进入循环命令
循环命令
- 点击特别关注(也相当于页面刷新)
- 查看第一条时间属性是否有 秒 关键字,若有则继续执行,否则返回命令1
- 点击评论按钮
- 输入文本
- 点击按钮(转发我的微博)
- 点击按钮(评论)返回命令1
技术选择
上面的需求分析的核心是模拟用户操作浏览器,支持模拟操作的技术有几个;
phantomjs 无界面,不方便开发。
slimerjs 火狐浏览器,基于phantomjs,脑子一热选了这个,开发中感觉语法不方便。
caperjs 基于上面两个的封装。建议使用这个。
selenium 这个就比较牛逼了,具体可去看官网。python开发很方便。
关键代码
登陆代码
//打开微博登陆界面
page.open("http://weibo.com/", function(status) {
if (status == "success") {
console.log("The title of the page is: "+ page.url);
}
else {
console.log("Sorry, the page is not loaded");
}
//需要等足够长的时间等页面完全加载。开发中发现如果当完全加载后会重置用户//密码中的信息。
slimer.wait(5000);
//登陆信息录入 config是配置文件引入
page.evaluate(function (config) {
console.log('message from the web page');
document.querySelector('#loginname').value = config.username;
var password = document.querySelector("input[name='password']");
password.value = config.password;
return document.querySelector("div.login_btn > a").click();
}, config);
//判断是否跳转到个人主页
waitForEver(2000, function () {
console.log("The title of the page is: "+ page.url);
return page.url.indexOf('home') !== -1;
}, function () {
clickfollows(page);
})
})
循环执行
function loopFollows(callback) {
console.log('loopFollows');
//点击特别关注
var commitBtn = page.evaluate(function () {
return document.querySelector("div.lev_Box > div > div > a");
});
console.log('commitBtn='+commitBtn);
if(commitBtn) {
commitBtn.click();
}
slimer.wait(5000);
//判断是否进入特别关注
if(page.url.indexOf('isspecialgroup') === -1) {
callback();
return ;
}
//判断是否有最近1分钟内发布的消息
var elements = page.evaluate(function () {
return document.querySelectorAll("div.WB_detail > div.WB_from > a");
});
console.log('clickfollows elements='+elements.length);
let isNeed=false;
for(var i=0; i<elements.length; i++) {
if(i < 2) {
var element = elements[i];
var text = element.innerText;
// fs.write('./log.txt', text, 'a');
if(text.indexOf('秒') !== -1) {
isNeed = true;
}
}
}
console.log('clickfollows isNeed='+isNeed);
if(!isNeed) {
callback();
return;
}
page.scrollPosition = { top: 400, left: 0 };
slimer.wait(200);
//点击评论按钮
var elements = page.evaluate(function () {
document.querySelectorAll("div.WB_handle > ul > li > a")[2].click();
});
slimer.wait(500);
//点击输入评论文本
var element = page.evaluate(function () {
return document.querySelector("div.p_input > textarea");
});
console.log('clickfollows element='+element);
if(!element) {
callback();
return ;
}
element.value=config.commit;
//点击转发到我的评论
page.evaluate(function () {
document.querySelector("div.WB_publish > div > div > ul > li > label").click();
});
slimer.wait(200);
//点击评论按钮
page.evaluate(function () {
document.querySelector("div.WB_publish > div > div > a").click();
});
callback(60000);
}
吐槽
1、slimerjs提供的api不足,比如很常见的waitfor都没有,需要自己实现。或者像我很多时候用slimer.wait()来做。
function waitForEver(time, testFx, onReady) {
time = time || 250;
window.setTimeout(function() {
var condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
if (!condition ) {
// If not time-out yet and condition not yet fulfilled
waitForEver(time, testFx, onReady);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
}
}, time); //< repeat check every 250ms
};
2、上面代码很多定时的时间可根据网速机器自行调整。我给同事用的时候就发现他提供的电脑比我开发用的差一些。需要做调整。很多细节也没做精细设计,比如重复自动登陆。目前还是暴力的重启应用。
3、使用caperjs吧。看看官网API,很适合开发;或者selenium。