Java實(shí)踐練習(xí)輕松幾行實(shí)現(xiàn)追書(shū)神器
大家好,我是Spring小楊,一個(gè)有夢(mèng)想的Java司機(jī)。
前不久,有個(gè)老同學(xué)找到我,問(wèn)有沒(méi)有什么靠譜的追書(shū)神器?
我想著這玩意無(wú)非用爬蟲(chóng),但是還是得盡量低調(diào),不然牢底坐穿!
正版網(wǎng)站的資源很難爬下來(lái)的,所以書(shū)源還是只能搜盜版網(wǎng)站,某趣閣就是個(gè)不錯(cuò)的選擇。
說(shuō)干就干,我立刻用eclipse創(chuàng)建了一個(gè)Java項(xiàng)目,還是按照之前的配方,用Hutool做定時(shí)任務(wù)。
因?yàn)橐廊【W(wǎng)站信息,所以還是得借助jsoup。
jsoup 是一款Java 的HTML解析器,可直接解析某個(gè)URL地址、HTML文本內(nèi)容。它提供了一套非常省力的API,可通過(guò)DOM,CSS以及類似于jQuery的操作方法來(lái)取出和操作數(shù)據(jù)。
還是之前一樣的配方,不過(guò)這次加了jsoup和javax.mail。為什么要發(fā)送郵件呢?那是因?yàn)槲蚁胍〞r(shí)去檢測(cè)網(wǎng)站的小說(shuō)有沒(méi)有更新,如果更新了,就及時(shí)把最新的章節(jié)通過(guò)郵件的形式發(fā)送給我,那不是更好嗎?
這樣我就可以立刻知道小說(shuō)有沒(méi)有更新了,然后更新的話,去自己的郵箱看就行了。
郵箱里面是肯定沒(méi)有廣告的啦!
public static HashMap cache = new HashMap<>(); public static Map cookies = new HashMap<>(); public static String url = https://www.biquwx.la/xxx/;
首先,定義幾個(gè)成員變量,分別是緩存cache,cookie 和 url。我就不用數(shù)據(jù)庫(kù)了,用一個(gè)靜態(tài)的HashMap來(lái)做緩存。cookie是每次爬取網(wǎng)頁(yè)后保存的,就是盡量模擬得像我瀏覽器訪問(wèn)。最后是url,就是小說(shuō)網(wǎng)站的實(shí)際地址,大概是這么一個(gè)目錄。
如果有更新,那就一定會(huì)出現(xiàn)在這個(gè)網(wǎng)頁(yè)!
下面是我發(fā)送請(qǐng)求的代碼:
Connection con = Jsoup.connect(url) .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0") .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") .header("Accept-Language","zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3") .header("Accept-Encoding", "gzip, deflate") .header("Connection","keep-alive") .header("Upgrade-Insecure-Requests", "1").cookies(cookies);
為了不希望他一下子發(fā)送太多郵件,我單獨(dú)設(shè)置了一個(gè)起始章節(jié),放在txt文本里面的。
里面就一個(gè)最新的章節(jié)標(biāo)題:
已經(jīng)發(fā)送過(guò)的章節(jié),我把它放到緩存中,不再重復(fù)發(fā)送:
//先檢查是否已經(jīng)在緩存中 if(cache.containsKey(element.text())){ System.out.println(element.text()+ "已經(jīng)發(fā)送,無(wú)需重復(fù)發(fā)送!"); continue; }
最后,再用Java發(fā)送一份郵件到自己的郵箱就可以啦!
MailAccount account = new MailAccount(); account.setHost("smtp.163.com"); account.setPort(Integer.valueOf(465)); account.setAuth(true); account.setSslEnable(Boolean.valueOf(true)); account.setConnectionTimeout(1000L); account.setSocketFactoryFallback(true); account.setFrom("你的發(fā)送郵箱"); account.setUser("你的發(fā)送郵箱"); account.setPass("你發(fā)送郵箱的授權(quán)碼"); MailUtil.send(account, "xxxxxxxxx@qq.com",element.text() , content, true, new File[0]); System.out.println("發(fā)送成功!");
我用的是163郵箱,然后發(fā)到對(duì)應(yīng)的qq郵箱。
下面是我成功收到的小說(shuō)章節(jié)郵件:
配上定時(shí)任務(wù),效果是達(dá)到了, 但是這個(gè)還是得放在服務(wù)器上運(yùn)行才好,不然總不可能一直開(kāi)著電腦吧,哈哈。
全部源代碼如下:
/** * 自動(dòng)發(fā)送小說(shuō)最新章節(jié) */ public static void sendMail() throws IOException{ System.out.println("開(kāi)始準(zhǔn)備爬取.."); Connection con = Jsoup.connect(url) .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0") .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") .header("Accept-Language","zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3") .header("Accept-Encoding", "gzip, deflate") .header("Connection","keep-alive") .header("Upgrade-Insecure-Requests", "1").cookies(cookies); Response execute = con.execute(); cookies = execute.cookies(); String body = execute.body().toString(); Document doc = Jsoup.parse(body); Elements as = doc.getElementsByTag("a"); boolean shouldSend = false; String start = FileUtil.readString("C:/start.txt", "UTF-8"); //讀取開(kāi)始章節(jié),如果服務(wù)重啟,必須重新修改該文件 for (Iterator iterator = as.iterator(); iterator.hasNext();) { Element element = (Element) iterator.next(); if(element.text().equals(start)){ shouldSend = true; } if(shouldSend && element.text().startsWith("第")){ //先檢查是否已經(jīng)在緩存中 if(cache.containsKey(element.text())){ System.out.println(element.text()+ "已經(jīng)發(fā)送,無(wú)需重復(fù)發(fā)送!"); continue; } con = Jsoup.connect(url + element.attr("href")); String content = Jsoup.parse(con.execute().body()).getElementById("content").html(); cache.put(element.text(), ""); MailAccount account = new MailAccount(); account.setHost("smtp.163.com"); account.setPort(Integer.valueOf(465)); account.setAuth(true); account.setSslEnable(Boolean.valueOf(true)); account.setConnectionTimeout(1000L); account.setSocketFactoryFallback(true); account.setFrom("你的發(fā)送郵箱"); account.setUser("你的發(fā)送郵箱"); account.setPass("授權(quán)碼"); // MailUtil.send(account, "你的接收郵箱",element.text() , content, true, new File[0]); System.out.println("發(fā)送成功!"); } } }
最后,爬蟲(chóng)雖好,不過(guò)自?shī)首詷?lè)一下就好了哈,本文也只是提供一個(gè)傳統(tǒng)思路,切勿用作違法用途哦~~
到此這篇關(guān)于Java實(shí)踐練習(xí)輕松幾行實(shí)現(xiàn)追書(shū)神器的文章就介紹到這了,更多相關(guān)Java 追書(shū)神器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于在Java中如何使用yaml的實(shí)例
這篇文章主要介紹了關(guān)于在Java中如何使用yaml的實(shí)例,YAML是一種輕量級(jí)的數(shù)據(jù)序列化格式。它以易讀、易寫(xiě)的文本格式表示數(shù)據(jù),支持列表、字典等各種數(shù)據(jù)結(jié)構(gòu),被廣泛應(yīng)用于配置文件、數(shù)據(jù)傳輸協(xié)議等領(lǐng)域,需要的朋友可以參考下2023-08-08java數(shù)據(jù)結(jié)構(gòu)與算法之桶排序?qū)崿F(xiàn)方法詳解
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之桶排序?qū)崿F(xiàn)方法,結(jié)合具體實(shí)例形式詳細(xì)分析了桶排序的概念、原理、實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2017-05-05圖解Java經(jīng)典算法快速排序的原理與實(shí)現(xiàn)
快速排序是基于二分的思想,對(duì)冒泡排序的一種改進(jìn)。主要思想是確立一個(gè)基數(shù),將小于基數(shù)的數(shù)放到基數(shù)左邊,大于基數(shù)的數(shù)字放到基數(shù)的右邊,然后在對(duì)這兩部分進(jìn)一步排序,從而實(shí)現(xiàn)對(duì)數(shù)組的排序2022-09-09Java spring webmvc如何實(shí)現(xiàn)控制反轉(zhuǎn)
這篇文章主要介紹了Java spring webmvc如何實(shí)現(xiàn)控制反轉(zhuǎn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08SpringBoot+ruoyi框架文件上傳和下載的實(shí)現(xiàn)
文件的上傳和下載功能,是項(xiàng)目開(kāi)發(fā)過(guò)程中比較常見(jiàn)的業(yè)務(wù)需求,本文主要介紹了SpringBoot+ruoyi框架文件上傳和文件下載的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09