目录 [隐藏]javascript
一波未平一波又起, 拿到这个需求的时候对我来讲仍是有挑战的,由于我以前并无作过这种东西,不过我知道,实现这种需求所用的技术无非就是爬虫,爬虫我仍是用过的,之前用JSOUP写过一个爬小说的程序,在个人博客园能够看到:
http://www.javashuo.com/article/p-mrouljwn-bn.htmlhtml
此次不一样,想要在论坛发消息首先是要登陆的,因此必需要一个帐号,接着是让爬虫登陆,这是最重要的一个步骤,登陆后获取Cookie存储,在加好友发消息的时候都要用到Cookie。java
在开发过程当中,遇到了很多难题,好比一开始的FormHash参数,这个参数一开始不知道哪里获取,最后发现登陆后在页面源代码中就有。cookie
FormHash是发送加好友等请求必须的参数,因此在爬虫模拟登陆后,进行爬取FormHash值,接着再请求加好友连接。app
public static Map<String, String> getCookie(String username, String password, String domain) throws Exception { SslUtils.ignoreSsl(); Connection conn = Jsoup.connect(Address.getLoginUrl(username, password, domain)); conn.method(Connection.Method.GET); conn.followRedirects(false); Connection.Response response; response = conn.execute(); System.err.println(response.body()); return response.cookies(); }
public static String getFormHash(String domain) throws Exception { SslUtils.ignoreSsl(); Connection conn = Jsoup.connect(Address.getFormHash(domain)); conn.followRedirects(false); Connection.Response response = conn.execute(); String HTMLRes = response.body(); String hashStr = "formhash="; int hashIndex = HTMLRes.lastIndexOf(hashStr); for (Map.Entry<String, String> c : response.cookies().entrySet()) { logger.info("Cookie:" + c.getKey() + "|" + c.getValue()); } System.err.println(response.body()); return HTMLRes.substring(hashIndex + hashStr.length(), hashIndex + hashStr.length() + 8); //formhash为8个字节长度 }
/** * @param cookies * @param touId 用户ID * @param msg 留言 * @param log 日志 * @param domain 域名 * @param formHash Hash值 * @throws Exception */ public static void hello(Map<String, String> cookies, String touId, String msg, TextArea log, String domain, String formHash) throws Exception { Platform.runLater(new Runnable() { @Override public void run() { try { log.appendText("HASH值获取:" + formHash + "\n"); } catch (Exception e) { e.printStackTrace(); } } }); SslUtils.ignoreSsl(); Connection conn = Jsoup.connect(Address.hello(touId, domain)); for (Map.Entry<String, String> entry : cookies.entrySet()) { conn.cookie(entry.getKey(), entry.getValue()); } conn.data("referer", Address.referer(touId, domain)); conn.data("addsubmit", "true"); conn.data("handlekey", String.format("a_friend_li_%S", touId)); conn.data("formhash", formHash); conn.data("note", msg); conn.data("gid", "1"); Platform.runLater(new Runnable() { @Override public void run() { log.appendText("开始发送:" + msg + "\t" + System.currentTimeMillis() + "\n"); } }); Document document = conn.post(); Platform.runLater(new Runnable() { @Override public void run() { logger.info(document.text()); if (document.text().contains("已发送") || document.text().contains("验证")) { log.appendText("已发送" + "\n"); } else { log.appendText("发送失败!" + "\n"); } // log.appendText(document.text()); } }); }
以上是这套流程的核心代码,最后将功能使用JavaFX展示:dom
完成。jsp
弊端:ide
这个程序目前是能够实现功能的,但只能对某些防御较为薄弱的DZ论坛使用,并且若是登陆遇到验证码,也是不行。post
在GUI窗体中存在TextArea日志区运行久了会没法刷新出日志信息,这个问题暂时找不到答案,我也没时间研究这个,毕竟用JavaFX的很少。ui