最近迷上了天蠶土豆寫的《大主宰》這本玄幻小說,無奈找不到下載鏈接。于是就萌生了自己爬取小說章節(jié)的想法,代碼其實很簡單,主要在于分析網(wǎng)頁結構、正則匹配以及文件保存.
1. 分析網(wǎng)頁結構
爬取小說主要需要爬取章節(jié)、正文,以及能保證爬取到所有的章節(jié)。以《大主宰》為例,其網(wǎng)頁結構如下:

可以看到小說正文包含在一個id為content的div里,這極大的幫助了我們的爬取.章節(jié)名稱保存在一個名為readtitle的js變量中.下一頁的url位于a標簽的href屬性中
2. 正則匹配
通過分析網(wǎng)頁結構,可以得到如下正則表達式:
- 章節(jié)名:
readtitle = "(.+?)" - 正文:
<div id="content">(.+?)</div> - 下一章:
→ <a href="(.+?)">
如果當前章節(jié)是最新章節(jié),那么其下一章的url是以 / 開頭的,我們可以根據(jù)這個判斷章節(jié)是否是最新章節(jié).
3. 運行結果
以爬取《大主宰》為例,截至至6月30號,其最新章節(jié)為第一千兩百五十四章 最后的贏家,爬取其小說內(nèi)容,保存為txt文件,測試結果如下:

4. 附錄
你可以通過jslinxiaoli@foxmail.com聯(lián)系我.
歡迎在github或者知乎上關注我 _.
也可以訪問個人網(wǎng)站: https://jslixiaolin.github.io
源代碼如下:
package com.lxl.txt;
import java.io.*;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 爬取小說txt文件
*
* @author lixiaolin
* @createDate 2016-06-28 19:38
*/
public class NovelGet {
public static void main(String[] args) {
String baseUrl = "http://www.00ksw.com/html/1/1343/";
String nextUrl = "597361.html";
String destFilePath = "D:\\test.txt";
System.out.println("開始爬取數(shù)據(jù)...");
long startTime = System.currentTimeMillis();
getNovel(baseUrl, nextUrl, destFilePath);
long endTime = System.currentTimeMillis();
System.out.println("用時 " + (endTime - startTime) / 1000 + "秒...");
}
public static void getNovel(String baseUrl, String nextUrl, String destFilePath) {
try {
File destFile = new File(destFilePath);
// 目標文件存在則刪除
if (!destFile.exists()) {
destFile.delete();
}
destFile.createNewFile();
FileWriter fw = new FileWriter(destFile);
String realUrl, resultContent;
StringBuffer sb = new StringBuffer();
BufferedReader br = null;
// 正文正則匹配表達式
Pattern contentPat = Pattern.compile("<div id=\"content\">(.+?)</div>");
// 標題正則表達式
Pattern titlePat = Pattern.compile("readtitle = \"(.+?)\"");
// 下一章正則表達式
Pattern nextPat = Pattern.compile("→ <a href=\"(.+?)\">");
Matcher matcher;
// 下一張的url以 / 開頭則是最新章節(jié)
while (!nextUrl.startsWith("/")) {
realUrl = baseUrl + nextUrl;
// 獲取目標url的response
br = new BufferedReader(new InputStreamReader(new URL(realUrl).openStream()));
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
// 替換空格和換行符
resultContent = sb.toString().replaceAll(" ", "").replaceAll("<br /><br />", "*****");
// 換行
fw.write("\r\n\r\n");
// 匹配標題
matcher = titlePat.matcher(resultContent);
if (matcher.find()) {
fw.write(matcher.group(1));
}
fw.write("\r\n");
// 匹配正文
matcher = contentPat.matcher(resultContent);
if (matcher.find()) {
fw.write(matcher.group(1));
}
// 匹配下一頁url
matcher = nextPat.matcher(resultContent);
if (matcher.find()) {
nextUrl = matcher.group(1);
}
// 清空
sb.delete(0, sb.length());
}
if (br != null) {
br.close();
}
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}