因版权问题,小说网站的URL、图片不可在此公布,读者根据自己想要爬取的网站,自行选择网站即可。
1.爬取小说章节内容,需要注意的大部分原创小说内容页是禁用右键的,无法直接选取页面内容进行元素检查,需要按F12,从上往下逐步选取元素。
2.利用IO流,将爬取的内容保存到本地文本文件。
本练习循序渐进,Demo1、首先爬取某一章节小说内容,Demo2、爬取完整一本小说内容,Demo3、爬取首页推荐榜中所有作品内容。
在项目中添加HttpClient、Jsoup依赖,参见本系列上两章。
Demo1:爬取某一章节小说内容
public static void main(String[] args) throws IOException {
//小说第一章URL,因版权问题,url屏蔽,读者可自行选择
String url = "https://xxx.xxxx.xxxx/xxxxx";
Connection connect = Jsoup.connect(url);
Document document = connect.get();
//经F12分析,章节的标题、内容组合选择器如下所示
Elements title = document.select("#j_chapterBox .text-wrap .main-text-wrap .text-head h3 .content-wrap");
Elements content = document.select("#j_chapterBox .text-wrap .main-text-wrap .read-content p");
//利用IO流将小说章节内容保存到本地
FileWriter fw = new FileWriter("d:/test/abc.txt");
fw.write(title.text() + "\r\n");
for (Element e : content) {
fw.write(e.text() + "\r\n");
}
fw.close();
}
Demo2、爬取完整一本小说内容
本Demo的思路是根据读取每章节的标题、内容,并读取“下一章”超链接中的href,以便发起网络请求爬取下一章内容。利用循环,即可实现自动爬取一本小说的内容。并爬取出本页面所显示的书名作为文件名。
这里注意,本Demo使用HttpClient做网络连接,Jsoup做内容解析,这是因为Jsoup虽然也可以进行网络连接,但是它存在的目的更是为了做HTML解析,它的网络连接方面的处理功能比之HTTPClient不可同日而语。在本Demo中,因为要不断的根据“下一章的”按钮,去发起新的网络请求,所以让适合的技术干适合的事情就势在必行了。
public static void main(String[] args) throws IOException {
//小说第一章URL,因版权问题,url屏蔽,读者可自行选择
String url = "https://xxx.xxxx.xxxx/xxxxx";;
Document document = Jsoup.connect(url).get();
Elements bookName = document.select("#j_textWrap .read-container .book-cover-wrap h1");
//建立文件输出流,保存文本文件,以小说名作为文件名
FileWriter fw = new FileWriter("d:/test/"+bookName.text()+".txt");
//通过HttpClients工具类创建一个httpClient对象,该用来发起HTTP请求
CloseableHttpClient httpClient = HttpClients.createDefault();
while(true) {
//创建一个“HTTP请求方法为Get”的一个对象
HttpGet httpGet = new HttpGet(url);
//通过httpClient发其Http请求,得到Http响应
CloseableHttpResponse response = httpClient.execute(httpGet);
//处理响应
//如果响应状态码是200,表示访问的网页是正常的
if (response.getStatusLine().getStatusCode() == 200) {
//拿到响应内容
HttpEntity entity = response.getEntity();
//将内容转换成String
String html = EntityUtils.toString(entity, "UTF-8");
//由Jsoup解析由HttpClient获取的HTML文档
document = Jsoup.parse(html);
//Jsoup通过id、class、标签,解析HTML文档,拿到我们业务上想要的数据
Elements title = document.select("#j_chapterBox .text-wrap .main-text-wrap .text-head h3 .content-wrap");
Elements content = document.select("#j_chapterBox .text-wrap .main-text-wrap .read-content p");
//解析“下一章”按钮,得到下一章的URL
Elements next = document.select("#j_chapterNext");
String href = next.attr("href");
String prefix = "https:";
url = prefix + href;
//如果爬取不到内容,说明本书已爬完最后一章,结束
if(url.equals("https:")){
break;
}
fw.write(title.text()+"\r\n");
for (Element e : content) {
fw.write(e.text()+"\r\n");
}
}
}
fw.close();
}
Demo3、爬取首页推荐榜中所有作品内容
本次爬取首页强推榜所有书籍。
点击强推榜单中的书籍超链接,会进入如下图所示的书籍首页。点击书籍的免费试读,可以进入到如Demo1、Demo2中的小说第一章的URL。
分析首页强推榜HTML代码、免费试读按钮代码,得出思路如下:
1.访问首页,解析强推榜中所有书籍
2.利用循环进入强推榜列表中所有书籍的主页
3.在书籍主页中,通过解析“免费试读”按钮,进入到第一章URL
4.根据Demo2中的读取完整一本小说内容,整合实现本Demo
代码如下:
public static void main(String[] args) throws IOException {
Document document = null;
String prefix = "https:";
//小说网站首页,url屏蔽,读者可自行选择
String url = "https://xxx.xxxx.xxxx/";
CloseableHttpClient httpClient = HttpClients.createDefault();
//访问小说网首页
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
String html = EntityUtils.toString(entity, "UTF-8");
document = Jsoup.parse(html);
//解析推榜单,得到书籍标题和href
Elements books = document.select(".wrap .index-two-wrap .book-list-wrap .book-list ul li strong a");
for (Element book : books) {
url = prefix + book.attr("href");
//进入书籍主页
httpGet = new HttpGet(url);
response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
entity = response.getEntity();
html = EntityUtils.toString(entity, "UTF-8");
document = Jsoup.parse(html);
//解析书籍主页中的“免费阅读”按钮,得到书籍第一章的URL
url =prefix+ document.select("#readBtn").attr("href");
//根据强推榜中的书籍标题,通过IO流,为每一本小说创建文件名
FileWriter fw = new FileWriter("d:/test/" + book.text() + ".txt");
//循环读取每一章节的内容,并使用IO流存储到对应的文件中
while (true) {
httpGet = new HttpGet(url);
response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
entity = response.getEntity();
//将内容转换成String
html = EntityUtils.toString(entity, "UTF-8");
document = Jsoup.parse(html);
Elements title = document.select("#j_chapterBox .text-wrap .main-text-wrap .text-head h3 .content-wrap");
Elements content = document.select("#j_chapterBox .text-wrap .main-text-wrap .read-content p");
Elements next = document.select("#j_chapterNext");
String href = next.attr("href");
url = prefix + href;
if (url.equals("https:")) {
break;
}
fw.write(title.text() + "\r\n");
for (Element e : content) {
fw.write(e.text() + "\r\n");
}
}
}
fw.close();
}
}
}
}```