目錄 [隱藏]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