目录 [隐藏]
- 1 思路:
- 2 代码:
- 2.1 登录,获取Cookie:
- 2.2 获取FormHash:
- 2.3 发送加好友请求并留言:
思路:
一波未平一波又起, 拿到这个需求的时候对我来说还是有挑战的,因为我之前并没有做过这种东西,不过我知道,实现这种需求所用的技术无非就是爬虫,爬虫我还是用过的,以前用JSOUP写过一个爬小说的程序,在我的博客园可以看到:
https://www.cnblogs.com/yangchaojie/p/9203876.html
这次不同,想要在论坛发消息首先是要登录的,所以必须要一个账号,接着是让爬虫登录,这是最重要的一个步骤,登录后获取Cookie存储,在加好友发消息的时候都要用到Cookie。
在开发过程中,遇到了不少难题,比如一开始的FormHash参数,这个参数一开始不知道哪里获取,最后发现登录后在页面源代码中就有。
FormHash是发送加好友等请求必须的参数,所以在爬虫模拟登录后,进行爬取FormHash值,接着再请求加好友链接。
代码:
登录,获取Cookie:
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(); }
获取FormHash:
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 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 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展现:
完成。
弊端:
这个程序目前是可以实现功能的,但只能对某些防护较为薄弱的DZ论坛使用,而且如果登录遇到验证码,也是不行。
在GUI窗体中存在TextArea日志区运行久了会无法刷新出日志信息,这个问题暂时找不到答案,我也没时间研究这个,毕竟用JavaFX的不多。