因为在 网页游戏 http://www.erepublik.com/en
担任某个企业的运营负责人,日常事务是负责统计玩家工作量,出具报表和发工资
由于游戏模式的固定化,所以考虑使用计算机帮我完成统计和出具报表的任务
一开始的想法是通过httpbuilder来抓取网页信息,然后将关键信息发送保存,但是由于grails和httpbuilder存在一个xml包的冲突,遂放弃
偶然间得知一个名为 greasemonkey 的fx插件,有了这个,我就可以通过js来控制其他host的dom结构,
由于是浏览器控件,没有js的安全控制,我可以将数据发送到后台,
前端部分和grails部分都比较简单,所以在数据库方面采用了mongodb..
作为一个自娱自乐的工具,已经是潮了 由于还要定时打开页面 自然要用上selenium-rc
greasemonkey的介绍 http://diveintogreasemonkey.org/toc/
mongodb的介绍 http://www.mongodb.org/display/DOCS/Home
selenium-rc插件 http://www.grails.org/Selenium+plugin
greasemonkey 的代码
访问的html页面 http://economy.erepublik.com/en/company/employees/smart-s-bread-good-/231891/46
// ==UserScript==
// @name Record Erepublik Work
// @namespace http://economy.erepublik.com/en/company/employees
// @include http://economy.erepublik.com/en/company/employees*
// ==/UserScript==
var employees = document.evaluate(
"//td[@class='el_employee']/div",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);
var results = document.evaluate(
"//td[@class='el_day']",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);
var results_currents = document.evaluate(
"//td[@class='el_day current']",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);
var tokens = window.location.href.split('/')
var results = []
var summap = {company:tokens[tokens.length-2],
week:tokens[tokens.length-1],
results: results,
time: (new Date()).getTime()}
for(var i=0; i<employees.snapshotLength; i++){
var employee = employees.snapshotItem(i)
var identity = employee.childNodes[1].innerHTML;
results[results.length] = {id:identity,sum:0}
//alert(employee.childNodes[1].firstChild.innerHTML);
}
for(var j=0; j<results.snapshotLength;j++){
var result = results.snapshotItem(j)
if(result.childNodes.length > 1){
results[parseInt(j/6)].sum += parseInt(result.childNodes[1].innerHTML, 10)
}
}
for(var j=0; j<results_currents.snapshotLength;j++){
var result = results_currents.snapshotItem(j)
if(result.childNodes.length > 1){
results[j].sum += parseInt(result.childNodes[1].innerHTML, 10)
}
}
function obj2str(o){
var r = [];
if(typeof o == "string" || o == null) {
return o;
}
if(typeof o == "object"){
if(!o.sort){
r[0]="{"
for(var i in o){
r[r.length]=i;
r[r.length]=":";
r[r.length]=obj2str(o[i]);
r[r.length]=",";
}
r[r.length-1]="}"
}else{
r[0]="["
for(var i =0;i<o.length;i++){
r[r.length]=obj2str(o[i]);
r[r.length]=",";
}
r[r.length-1]="]"
}
return r.join("");
}
return o.toString();
}
GM_xmlhttpRequest({
method: "POST",
url: "http://localhost:8080/erepublik/workResult/input",
data: "jsonstr="+obj2str(summap),
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
onload: function(response) {
console.info(response)
}
});
grails
package erepublik
import grails.converters.JSON;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
class WorkResultController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST", input : "POST"]
def index = {
redirect(action: "list", params: params)
}
def input = {
def resultsum = JSON.parse(params.jsonstr)
def m = new Mongo()
def db = m.getDB("erepublik")
def coll = db.getCollection("work")
//coll.drop()
BasicDBObject query = new BasicDBObject();
query.put("week", resultsum.week);
query.put("company", resultsum.company);
def findone = coll.findOne(query);
if(findone){
println 'update'
coll.update(findone , resultsum as BasicDBObject)
}else{
println 'insert'
coll.insert(resultsum as BasicDBObject)
}
/*DBCursor cur = coll.find();
while(cur.hasNext()) {
System.out.println(cur.next());
}*/
render 0
}
def list = {
def results = []
def m = new Mongo()
def db = m.getDB("erepublik")
def coll = db.getCollection("work")
[workResultInstanceList: coll.find(), workResultInstanceTotal: coll.find().count()]
}
def create = {
def workResultInstance = new WorkResult()
workResultInstance.properties = params
return [workResultInstance: workResultInstance]
}
def save = {
def workResultInstance = new WorkResult(params)
if (workResultInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'workResult.label', default: 'WorkResult'), workResultInstance.id])}"
redirect(action: "show", id: workResultInstance.id)
}
else {
render(view: "create", model: [workResultInstance: workResultInstance])
}
}
def show = {
def workResultInstance = WorkResult.get(params.id)
if (!workResultInstance) {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'workResult.label', default: 'WorkResult'), params.id])}"
redirect(action: "list")
}
else {
[workResultInstance: workResultInstance]
}
}
def edit = {
def workResultInstance = WorkResult.get(params.id)
if (!workResultInstance) {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'workResult.label', default: 'WorkResult'), params.id])}"
redirect(action: "list")
}
else {
return [workResultInstance: workResultInstance]
}
}
def update = {
def workResultInstance = WorkResult.get(params.id)
if (workResultInstance) {
if (params.version) {
def version = params.version.toLong()
if (workResultInstance.version > version) {
workResultInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'workResult.label', default: 'WorkResult')] as Object[], "Another user has updated this WorkResult while you were editing")
render(view: "edit", model: [workResultInstance: workResultInstance])
return
}
}
workResultInstance.properties = params
if (!workResultInstance.hasErrors() && workResultInstance.save(flush: true)) {
flash.message = "${message(code: 'default.updated.message', args: [message(code: 'workResult.label', default: 'WorkResult'), workResultInstance.id])}"
redirect(action: "show", id: workResultInstance.id)
}
else {
render(view: "edit", model: [workResultInstance: workResultInstance])
}
}
else {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'workResult.label', default: 'WorkResult'), params.id])}"
redirect(action: "list")
}
}
def delete = {
def workResultInstance = WorkResult.get(params.id)
if (workResultInstance) {
try {
workResultInstance.delete(flush: true)
flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'workResult.label', default: 'WorkResult'), params.id])}"
redirect(action: "list")
}
catch (org.springframework.dao.DataIntegrityViolationException e) {
flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'workResult.label', default: 'WorkResult'), params.id])}"
redirect(action: "show", id: params.id)
}
}
else {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'workResult.label', default: 'WorkResult'), params.id])}"
redirect(action: "list")
}
}
}