HttpClients+Jsoup抓取笔趣阁小说,并保存到本地TXT文件
前言
首先先介绍一下Jsoup:(摘自官网)
jsoup is a Java library for working with real-world HTML. It provides a very convenient API for extracting and manipulating data, using the best of DOM, CSS, and jquery-like methods.
Jsoup俗称“大杀器”,具体的使用大家可以看 jsoup中文文档
代码编写
首先maven引包:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.9</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
封装几个方法(思路大多都在注解里面,相信大家都看得懂):
/**
* 创建.txt文件
*
* @param fileName 文件名(小说名)
* @return File对象
*/
public static File createFile(String fileName) {
//获取桌面路径
String comPath = FileSystemView.getFileSystemView().getHomeDirectory().getPath();
//创建空白文件夹:networkNovel
File file = new File(comPath + "\\networkNovel\\" + fileName + ".txt");
try {
//获取父目录
File fileParent = file.getParentFile();
if (!fileParent.exists()) {
fileParent.mkdirs();
}
//创建文件
if (!file.exists()) {
file.createNewFile();
}
} catch (Exception e) {
file = null;
System.err.println("新建文件操作出错");
e.printStackTrace();
}
return file;
} /**
* 字符流写入文件
*
* @param file file对象
* @param value 要写入的数据
*/
public static void fileWriter(File file, String value) {
//字符流
try {
FileWriter resultFile = new FileWriter(file, true);//true,则追加写入
PrintWriter myFile = new PrintWriter(resultFile);
//写入
myFile.println(value);
myFile.println("\n"); myFile.close();
resultFile.close();
} catch (Exception e) {
System.err.println("写入操作出错");
e.printStackTrace();
}
} /**
* 采集当前url完整response实体.toString()
*
* @param url url
* @return response实体.toString()
*/
public static String gather(String url,String refererUrl) {
String result = null;
try {
//创建httpclient对象 (这里设置成全局变量,相对于同一个请求session、cookie会跟着携带过去)
CloseableHttpClient httpClient = HttpClients.createDefault();
//创建get方式请求对象
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Content-type", "application/json");
//包装一下
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
httpGet.addHeader("Referer", refererUrl);
httpGet.addHeader("Connection", "keep-alive"); //通过请求对象获取响应对象
CloseableHttpResponse response = httpClient.execute(httpGet);
//获取结果实体
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(response.getEntity(), "GBK");
} //释放链接
response.close();
}
//这里还可以捕获超时异常,重新连接抓取
catch (Exception e) {
result = null;
System.err.println("采集操作出错");
e.printStackTrace();
}
return result;
} /**
* 使用jsoup处理html字符串,根据规则,得到当前章节名以及完整内容跟下一章的链接地址
* 每个站点的代码风格都不一样,所以规则要根据不同的站点去修改
* 比如这里的文章内容直接用一个div包起来,而有些站点是每个段落用p标签包起来
* @param html html字符串
* @return Map<String,String>
*/
public static Map<String, String> processor(String html) {
HashMap<String, String> map = new HashMap<>();
String chapterName;//章节名
String chapter = null;//完整章节(包括章节名)
String next = null;//下一章链接地址
try {
//解析html格式的字符串成一个Document
Document doc = Jsoup.parse(html); //章节名称
Elements bookname = doc.select("div.bookname > h1");
chapterName = bookname.text().trim();
chapter = chapterName +"\n"; //文章内容
Elements content = doc.select("div#content");
String replaceText = content.text().replace(" ", "\n");
chapter = chapter + replaceText; //下一章
Elements nextText = doc.select("a:matches((?i)下一章)");
if (nextText.size() > 0) {
next = nextText.attr("href");
} map.put("chapterName", chapterName);//章节名称
map.put("chapter", chapter);//完整章节内容
map.put("next", next);//下一章链接地址
} catch (Exception e) {
map = null;
System.err.println("处理数据操作出错");
e.printStackTrace();
}
return map;
} /**
* 递归写入完整的一本书
* @param file file
* @param baseUrl 基础url
* @param url 当前url
* @param refererUrl refererUrl
*/
public static void mergeBook(File file, String baseUrl, String url, String refererUrl) {
String html = gather(baseUrl + url,baseUrl +refererUrl);
Map<String, String> map = processor(html);
//追加写入
fileWriter(file, map.get("chapter"));
System.out.println(map.get("chapterName") + " --100%");
if (!StringUtils.isEmpty(map.get("next"))) {
//递归
mergeBook(file, baseUrl, map.get("next"),url);
}
}
main测试:
public static void main(String[] args) {
//需要提供的条件:站点;小说名;第一章的链接;refererUrl
String baseUrl = "http://www.biquge.com.tw";
File file = createFile("斗破苍穹");
mergeBook(file, baseUrl, "/1_1999/1179371.html","/1_1999/");
}
效果





给大家看一下我之前爬取的数据,多开几个进程,挂机爬,差不多七个G,七百八十多部小说

代码开源
代码已经开源、托管到我的GitHub、码云:
GitHub:https://github.com/huanzi-qch/spider
码云:https://gitee.com/huanzi-qch/spider
HttpClients+Jsoup抓取笔趣阁小说,并保存到本地TXT文件的更多相关文章
- Jsoup-基于Java实现网络爬虫-爬取笔趣阁小说
注意!仅供学习交流使用,请勿用在歪门邪道的地方!技术只是工具!关键在于用途! 今天接触了一款有意思的框架,作用是网络爬虫,他可以像操作JS一样对网页内容进行提取 初体验Jsoup <!-- Ma ...
- bs4爬取笔趣阁小说
参考链接:https://www.cnblogs.com/wt714/p/11963497.html 模块:requests,bs4,queue,sys,time 步骤:给出URL--> 访问U ...
- Python爬取笔趣阁小说,有趣又实用
上班想摸鱼?为了摸鱼方便,今天自己写了个爬取笔阁小说的程序.好吧,其实就是找个目的学习python,分享一下. 1. 首先导入相关的模块 import os import requests from ...
- python应用:爬虫框架Scrapy系统学习第四篇——scrapy爬取笔趣阁小说
使用cmd创建一个scrapy项目: scrapy startproject project_name (project_name 必须以字母开头,只能包含字母.数字以及下划线<undersco ...
- scrapycrawl 爬取笔趣阁小说
前言 第一次发到博客上..不太会排版见谅 最近在看一些爬虫教学的视频,有感而发,大学的时候看盗版小说网站觉得很能赚钱,心想自己也要搞个,正好想爬点小说能不能试试做个网站(网站搭建啥的都不会...) 站 ...
- python入门学习之Python爬取最新笔趣阁小说
Python爬取新笔趣阁小说,并保存到TXT文件中 我写的这篇文章,是利用Python爬取小说编写的程序,这是我学习Python爬虫当中自己独立写的第一个程序,中途也遇到了一些困难,但是最后 ...
- scrapy框架爬取笔趣阁
笔趣阁是很好爬的网站了,这里简单爬取了全部小说链接和每本的全部章节链接,还想爬取章节内容在biquge.py里在加一个爬取循环,在pipelines.py添加保存函数即可 1 创建一个scrapy项目 ...
- 免app下载笔趣阁小说
第一次更新:发现一个问题,就是有时候网页排版有问题的话容易下载到多余章节,如下图所示: 网站抽风多了一个正文一栏,这样的话就会重复下载1603--1703章节. 解决办法: 于是在写入内容前加了一个章 ...
- 笔趣阁小说 selenium爬取
import re from time import sleep from lxml import etree from selenium import webdriver options = web ...
随机推荐
- 初学者必看的文章:在VM12中安装 RedHat RHEL7.2 系统的详细步骤:看我如何操纵RHEL系统
一.开始安装 1)新建虚拟机 RHEL7.2 2)成功引导系统--开机出现此画面 Install Red Hat EnterpriseLinux 7.2 安装RHLE7.2 操作系统 Test th ...
- Scrum的3种角色划分--2048小游戏
WBS分析: 敏捷开发 Scrum的3种角色划分:产品负责人PO(Product Owner).SM(ScrumMaster).开发团队(Team) 职责: PO:负责在限定期限内拟定可能的最有价值的 ...
- Forward团队-爬虫豆瓣top250项目-开发文档
项目地址:https://github.com/xyhcq/top250 我在本次项目中负责写爬虫中对数据分析的一部分,根据马壮分析过的html,我来进一步写代码获取数据,具体的功能及实现方法我已经写 ...
- Robust Influence Maximization
一. 研究背景 在社会和经济网络中,影响最大化问题在过去十年中得到广泛的研究,由于其广泛应用于病毒式营销[1,2],突破检测[3],谣言监测[4]等.例如公司可以通过向初始用户(称为种子)发送免费 ...
- linux vg lv pv
= pv由物理卷或者分区组成 pv可以组成一个或者多个vg vg可以分成多个lv 方便扩展 pvs vgs lvs 可以查看当前存在的pv vg lv 我的centos硬盘20g 使用了一 ...
- C#轻量级通通讯组件StriveEngine —— C/S通信开源demo(2) —— 使用二进制协议 (附源码)
前段时间,有几个研究ESFramework通信框架的朋友对我说,ESFramework有点庞大,对于他们目前的项目来说有点“杀鸡用牛刀”的意思,因为他们的项目不需要文件传送.不需要P2P.不存在好友关 ...
- 理解 Linux 的虚拟内存
前言 前不久组内又有一次我比较期待的分享:”Linux 的虚拟内存”.是某天晚上加班时,我们讨论虚拟内存的概念时,leader 发现几位同事对虚拟内存认识不清后,特意给这位同学挑选的主题(笑). 我之 ...
- Go语言map
map 是一种特殊的数据结构:一种元素对(pair)的无序集合,pair 的一个元素是 key,对应的另一个元素是 value,所以这个结构也称为关联数组或字典.这是一种快速寻找值的理想结构:给定 k ...
- Mybatis框架七:三种方式整合Spring
需要的jar包: 新建lib文件夹放入jar包,Build Path-->Add To Build Path之后: 原始Dao开发示例: src下:新建核心配置文件sqlMapConfig.xm ...
- Java回调机制总结
调用和回调机制 在一个应用系统中, 无论使用何种语言开发, 必然存在模块之间的调用, 调用的方式分为几种: 1.同步调用 同步调用是最基本并且最简单的一种调用方式, 类A的方法a()调用类B的方法b( ...