这个工具是方便版主结贴而设计,利用正则分析帖子的内容加上CSDN提供的API。 仅仅作为小技术分享帖。 将要处理的帖子链接放到“Topics.txt”文件中,如: ---Topics.txt--- http://topic.csdn.net/u/20080612/09/1a80296f-ac45-4efd-97ba-f9dd60a9a93f.html http://topic.csdn.net/u/20080612/09/971b98b6-9ba6-4a0a-8ae8-c8baf3ccf064.html 将帖子里两部分合并保存为.hta文件,即可直接运行。 日志将放到log.txt文件中 <html> <title>CSDN结贴机--清洁工2008版</title> <head> <hta:application id="sofa" icon="sofa.ico" /> </head> <body> <div> 用户名:<input type="text" id="TextUsername" /> 密码:<input type="password" id="TextPassword" /> 结贴方式:<select id="SelectCheckOutStyle"><option>按人平均</option><option>按楼平均</option><select/> <input type="button" value="开始结贴" onclick="ButtonStartClick();" id="ButtonStart" /> </div> <div style="width:100%; height:80%"> <textarea id="TextareaLog" style="width:100%; height:100%"></textarea> </div> <script language="javascript" type="text/javascript"> var ForAppending = 8; // 追加模式 var ForReading = 1; // 读取模式 var ForWriting = 2; // 写入模式 var fso = new ActiveXObject("Scripting.FileSystemObject"); // 文件系统 var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); // http访问 var textareaLog = document.getElementById("TextareaLog"); // 日志文本框 var textUsername = document.getElementById("TextUsername"); // 用户名 var textPassword = document.getElementById("TextPassword"); // 密码 var selectCheckOutStyle = document.getElementById("SelectCheckOutStyle"); // 结贴方式 /// <summary> /// 获得值在列表中的位置 /// </summary> /// <param name="array">列表</param> /// <param name="value">值</param> /// <returns>返回值在列表中的位置</returns> function IndexOf(array, value) { for (var i = 0; i < array.length; i++) if (array[i] == value) return i; return -1; } /// <summary> /// 读取文本文件中的字符串 /// </summary> /// <param name="filename">文件名</param> /// <returns>返回文本文件中的字符串</returns> function GetFileText(filename) { if (!fso.FileExists(filename)) return ""; var istream = fso.OpenTextFile(filename, ForReading); if (!istream) return ""; try { var contents = istream.ReadAll(); istream.Close(); } catch (e) { return ""; } return contents; } /// <summary> /// 将字符串追加到文本文件最后 /// </summary> /// <param name="filename">文件名</param> /// <param name="text">所要追加的字符串</param> /// <returns>返回文本文件中的字符串</returns> function AppendFileText(filename, text) { var istream = fso.OpenTextFile(filename, ForAppending, true); if (!istream) return; try { istream.write(text); istream.Close(); } catch (e) { } } /// <summary> /// 将字符串写到文本文件最后 /// </summary> /// <param name="filename">文件名</param> /// <param name="text">所要追加的字符串</param> /// <returns>返回文本文件中的字符串</returns> function WriteFileText(filename, text) { var istream = fso.OpenTextFile(filename, ForWriting, true); if (!istream) return; try { istream.write(text); istream.Close(); } catch (e) { } } /// <summary> /// 结贴 /// </summary> /// <param name="username">用户名</param> /// <param name="password">用户口令</param> /// <param name="topicUrl">帖子链接</param> /// <param name="forumId">版块ID</param> /// <param name="points">给分列表</param> /// <returns>返回反馈信息</returns> function CheckOut(username, password, topicUrl, forumId, points) { var contentText = '<?xml version="1.0" encoding="utf-8"?>/n' + '<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">/n' + ' <soap12:Body>/n' + ' <CheckOutTopic xmlns="http://www.csdn.net/">/n' + ' <identity>/n' + ' <username>' + username + '</username>/n' + ' <password>' + password + '</password>/n' + ' </identity>/n' + ' <topicUrl>' + topicUrl + '</topicUrl>/n' + ' <forumId>' + forumId + '</forumId>/n' + ' <replyPoints>/n'; for (var i = 0; i < points.length; i++) { if (parseInt(points[i].point) <= 0) continue; // 没有得分则不用提交 contentText += ' <ReplyPoint>/n' + ' <replyId>' + points[i].replyId + '</replyId>/n' + ' <point>' + points[i].point + '</point>/n' + ' </ReplyPoint>/n'; } contentText += ' </replyPoints>/n' + ' </CheckOutTopic>/n' + ' </soap12:Body>/n' + '</soap12:Envelope>/n'; try { xmlhttp.open("post", "http://forum.csdn.net/OpenApi/forumapi.asmx", false); xmlhttp.setRequestHeader("CONTENT-LENGTH", contentText.length); xmlhttp.setRequestHeader("CONTENT-TYPE", "text/xml; charset=utf-8"); xmlhttp.send(contentText); return xmlhttp.responseText; } catch (e) { return ""; } } /// <summary> /// 构造结贴给分信息 /// </summary> /// <param name="replyId">回复Id</param> /// <param name="point">给分点数</param> /// <returns>返回给分信息</returns> function PointInfo(replyId, point) { this.replyId = replyId; this.point = point; } </script> <script language="javascript" type="text/javascript"> /// <summary> /// 读取页面文本 /// </summary> /// <param name="url">页面所在链接</param> /// <returns>返回页面文本</returns> function GetUrlText(url) { try { xmlhttp.open("get", url, false); xmlhttp.send(); return xmlhttp.responseText; } catch (e) { return ""; } } /// <summary> /// 分析回复内容 /// </summary> /// <param name="replyText">回复区域HTML文本</param> /// <returns>返回回复信息</returns> function ReplyInfo(replyText) { var re = //<a/s*csdnid=/"replyId/"/s*name="(.*?)"/s*/>/<//a/>/s*<table/s*class=/"item reply/"/s*csdnid="(.*?)".*?>.*?/<//table/>/g; if (re.exec(replyText)) this.replyId = RegExp.$1; // 回复ID var re = //<a/s*href=/"http/:hi.csdn.net//(.*?)/"/s*.*?/>/g; if (re.exec(replyText)) this.replyUser = RegExp.$1; // 回复用户名 var re = //<var/s*csdnid=/'replyDate/'/>(.*?)/<//var/>/g; if (re.exec(replyText)) this.replyDate = RegExp.$1; // 回复时间 var re = //<span/s*class=(/"|/')adminOpera(/"|/')/>/s*该回复于(.*?)被版主删除/s*/<//span/>/g; if (re.exec(replyText)) this.deleteDate = RegExp.$3; // 删除时间 var re = //<span/s*class=(/"|/')adminOpera(/"|/')/>/s*该回复于(.*?)被版主修改/s*/<//span/>/g; if (re.exec(replyText)) this.modifyDate = RegExp.$3; // 修改时间 } /// <summary> /// 分析帖子内容 /// </summary> /// <param name="topicText">帖子HTML文本</param> /// <returns>返回帖子信息</returns> function TopicInfo(topicText) { topicText = topicText.replace(//r/n/g, " "); var re = //<span/s*csdnid=/"isCheckOut/"/s*class=/"color_red/"/>(.*?)/<//span/>/g; if (re.exec(topicText)) this.isCheckOut = RegExp.$1; // 是否已经结贴 var re = //<meta/s*csdnid=/"sectionId/"/s*content=/"(.*?)/"(/s*//)*/>/g; if (re.exec(topicText)) this.forumId = RegExp.$1; // 版块ID var re = //<meta/s*id=/"topicViewUrl/"/s*csdnid=/"topicViewUrl/"/s*content=/"(.*?)/"(/s*//)*/>/g; if (re.exec(topicText)) this.topicUrl = RegExp.$1; // 帖子链接 var re = //<meta/s*csdnid=/"description/"/s*content=/"(.*?)/"/s*name=/"description/"(/s*//)*/>/g; if (re.exec(topicText)) this.description = RegExp.$1; // 帖子主题 var re = //<var/s*id=/"point/"/s*csdnid=/"topicPoint/"/>(.*?)/<//var/>/g; if (re.exec(topicText)) this.point = RegExp.$1; // 帖子点数 var re = //<var/s*csdnid=/"replyCount/">(.*?)/<//var/>/g; if (re.exec(topicText)) this.replyCount = RegExp.$1; // 回复次数 var re = //<a/s*href=/"http/:hi.csdn.net//(.*?)/"/s*.*?/>/g; if (re.exec(topicText)) this.username = RegExp.$1; // 楼主 var re = //<var/s*csdnid=/"topicPostDate/">(.*?)/<//var/>/g; if (re.exec(topicText)) this.topicPostDate = RegExp.$1; // 发帖时间 var matchs = topicText.match(//<a/s*csdnid=/"replyId/"/s*name="(.*?)"/s*/>/<//a/>/s*<table/s*class=/"item reply/"/s*csdnid="(.*?)".*?>.*?/<//table/>/g); this.replys = new Array(); for (var i = 0; matchs && i < matchs.length; i++) { var replyInfo = new ReplyInfo(matchs[i]); this.replys.push(replyInfo); } } /// <summary> /// 分析错误信息 /// </summary> /// <param name="errorText">服务器返回的XML文本</param> /// <returns>返回错误信息</returns> function ErrorInfo(errorText) { errorText = errorText.replace(//r/n/g, " "); var re = //<errId/>(.*?)/<//errId/>/g; if (re.exec(errorText)) this.errId = RegExp.$1; // 错误号 var re = //<errInfo/>(.*?)/<//errInfo/>/g; if (re.exec(errorText)) this.errInfo = RegExp.$1; // 错误信息 } /// <summary> /// 添加日志 /// </summary> /// <param name="text">日志文本</param> function AppendLog(text) { if (textareaLog) textareaLog.value += text; AppendFileText("log.txt", text); } var topics = GetFileText("Topics.txt").split(//r/n/); // 帖子列表 /// <summary> /// 开始按钮点击事件 /// </summary> function ButtonStartClick() { for (var j = 0; j < topics.length; j++) { var text = GetUrlText(topics[j]); // 获得帖子的网页文本 var topicInfo = new TopicInfo(text); // 分析网页文本中的帖子信息 if (topicInfo.isCheckOut) { AppendLog("错误:" + topicInfo.topicUrl + "已经结过。/r/n"); continue; } var points = new Array(); var names = new Array(); for (var i = 0; parseInt(topicInfo.point) > 0 && i < topicInfo.replys.length; i++) // 帖子分数需要大于0 { // TODO : 判断回复的日期可以用topicInfo.replys[i].replyDate if (topicInfo.replys[i].deleteDate) continue; // 已被删除的回复 if (topicInfo.replys[i].replyUser.toLowerCase() == textUsername.value.toLowerCase()) continue; // 回复用户等于结贴用户 if (topicInfo.replys[i].replyUser.toLowerCase() == topicInfo.username.toLowerCase()) continue; // 回复用户等于楼主 switch (selectCheckOutStyle.selectedIndex) // 结贴的方式 { case 0: // 按人平均 if (IndexOf(names, topicInfo.replys[i].replyUser.toLowerCase()) < 0) // 判断已经给过分了 { points.push(new PointInfo(topicInfo.replys[i].replyId, 0)); names.push(topicInfo.replys[i].replyUser.toLowerCase()); } break; case 1: // 按楼平均 points.push(new PointInfo(topicInfo.replys[i].replyId, 0)); break; } } if (parseInt(topicInfo.point) > 0 && points.length <= 0) // 有分,但没有符合得分条件的回复 { AppendLog("错误:" + topicInfo.topicUrl + "没有符合得分条件的回复。/r/n"); continue; } if (points.length > 0) { var average = Math.floor(parseInt(topicInfo.point) / points.length); // 获得平均分 var spare = parseInt(topicInfo.point) % points.length; // 获得余数 for (var i = 0; i < points.length; i++) { if (spare > 0) { points[i].point = average + 1; spare--; } else points[i].point = average; } } var errorText = CheckOut(textUsername.value, textPassword.value, topicInfo.topicUrl, topicInfo.forumId, points); var errorInfo = new ErrorInfo(errorText); if (parseInt(errorInfo.errId) == 0) // 没有错误 AppendLog("成功:" + topicInfo.topicUrl + "已经结贴。/r/n"); else AppendLog("错误:" + topicInfo.topicUrl + "#" + errorInfo.errId + " 原因:" + errorInfo.errInfo + "/r/n"); } } </script> </body> </html>
CSDN结贴机--清洁工2008版
最新推荐文章于 2024-04-18 17:52:13 发布