前言

  首先先介绍一下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引包:

  1. <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.4</version>
    </dependency>
  2.  
  3. <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.9</version>
    </dependency>
  1. <dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.3</version>
    </dependency>

  封装几个方法(思路大多都在注解里面,相信大家都看得懂):

  1.   /**
  2. * 创建.txt文件
  3. *
  4. * @param fileName 文件名(小说名)
  5. * @return File对象
  6. */
  7. public static File createFile(String fileName) {
  8. //获取桌面路径
  9. String comPath = FileSystemView.getFileSystemView().getHomeDirectory().getPath();
  10. //创建空白文件夹:networkNovel
  11. File file = new File(comPath + "\\networkNovel\\" + fileName + ".txt");
  12. try {
  13. //获取父目录
  14. File fileParent = file.getParentFile();
  15. if (!fileParent.exists()) {
  16. fileParent.mkdirs();
  17. }
  18. //创建文件
  19. if (!file.exists()) {
  20. file.createNewFile();
  21. }
  22. } catch (Exception e) {
  23. file = null;
  24. System.err.println("新建文件操作出错");
  25. e.printStackTrace();
  26. }
  27. return file;
  28. }
  29.  
  30. /**
  31. * 字符流写入文件
  32. *
  33. * @param file file对象
  34. * @param value 要写入的数据
  35. */
  36. public static void fileWriter(File file, String value) {
  37. //字符流
  38. try {
  39. FileWriter resultFile = new FileWriter(file, true);//true,则追加写入
  40. PrintWriter myFile = new PrintWriter(resultFile);
  41. //写入
  42. myFile.println(value);
  43. myFile.println("\n");
  44.  
  45. myFile.close();
  46. resultFile.close();
  47. } catch (Exception e) {
  48. System.err.println("写入操作出错");
  49. e.printStackTrace();
  50. }
  51. }
  52.  
  53. /**
  54. * 采集当前url完整response实体.toString()
  55. *
  56. * @param url url
  57. * @return response实体.toString()
  58. */
  59. public static String gather(String url,String refererUrl) {
  60. String result = null;
  61. try {
  62. //创建httpclient对象 (这里设置成全局变量,相对于同一个请求session、cookie会跟着携带过去)
  63. CloseableHttpClient httpClient = HttpClients.createDefault();
  64. //创建get方式请求对象
  65. HttpGet httpGet = new HttpGet(url);
  66. httpGet.addHeader("Content-type", "application/json");
  67. //包装一下
  68. 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");
  69. httpGet.addHeader("Referer", refererUrl);
  70. httpGet.addHeader("Connection", "keep-alive");
  71.  
  72. //通过请求对象获取响应对象
  73. CloseableHttpResponse response = httpClient.execute(httpGet);
  74. //获取结果实体
  75. if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
  76. result = EntityUtils.toString(response.getEntity(), "GBK");
  77. }
  78.  
  79. //释放链接
  80. response.close();
  81. }
  82. //这里还可以捕获超时异常,重新连接抓取
  83. catch (Exception e) {
  84. result = null;
  85. System.err.println("采集操作出错");
  86. e.printStackTrace();
  87. }
  88. return result;
  89. }
  90.  
  91. /**
  92. * 使用jsoup处理html字符串,根据规则,得到当前章节名以及完整内容跟下一章的链接地址
  93. * 每个站点的代码风格都不一样,所以规则要根据不同的站点去修改
       * 比如这里的文章内容直接用一个div包起来,而有些站点是每个段落用p标签包起来
  94. * @param html html字符串
  95. * @return Map<String,String>
  96. */
  97. public static Map<String, String> processor(String html) {
  98. HashMap<String, String> map = new HashMap<>();
  99. String chapterName;//章节名
  100. String chapter = null;//完整章节(包括章节名)
  101. String next = null;//下一章链接地址
  102. try {
  103. //解析html格式的字符串成一个Document
  104. Document doc = Jsoup.parse(html);
  105.  
  106. //章节名称
  107. Elements bookname = doc.select("div.bookname > h1");
  108. chapterName = bookname.text().trim();
  109. chapter = chapterName +"\n";
  110.  
  111. //文章内容
  112. Elements content = doc.select("div#content");
  113. String replaceText = content.text().replace(" ", "\n");
  114. chapter = chapter + replaceText;
  115.  
  116. //下一章
  117. Elements nextText = doc.select("a:matches((?i)下一章)");
  118. if (nextText.size() > 0) {
  119. next = nextText.attr("href");
  120. }
  121.  
  122. map.put("chapterName", chapterName);//章节名称
  123. map.put("chapter", chapter);//完整章节内容
  124. map.put("next", next);//下一章链接地址
  125. } catch (Exception e) {
  126. map = null;
  127. System.err.println("处理数据操作出错");
  128. e.printStackTrace();
  129. }
  130. return map;
  131. }
  132.  
  133. /**
  134. * 递归写入完整的一本书
  135. * @param file file
  136. * @param baseUrl 基础url
  137. * @param url 当前url
  138. * @param refererUrl refererUrl
  139. */
  140. public static void mergeBook(File file, String baseUrl, String url, String refererUrl) {
  141. String html = gather(baseUrl + url,baseUrl +refererUrl);
  142. Map<String, String> map = processor(html);
  143. //追加写入
  144. fileWriter(file, map.get("chapter"));
  145. System.out.println(map.get("chapterName") + " --100%");
  146. if (!StringUtils.isEmpty(map.get("next"))) {
           //递归
  147. mergeBook(file, baseUrl, map.get("next"),url);
  148. }
  149. }

  main测试:

  1.   public static void main(String[] args) {
  2. //需要提供的条件:站点;小说名;第一章的链接;refererUrl
  3. String baseUrl = "http://www.biquge.com.tw";
  4. File file = createFile("斗破苍穹");
  5. mergeBook(file, baseUrl, "/1_1999/1179371.html","/1_1999/");
  6. }

效果

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

 

  代码开源

  代码已经开源、托管到我的GitHub、码云:

  GitHub:https://github.com/huanzi-qch/spider

  码云:https://gitee.com/huanzi-qch/spider

HttpClients+Jsoup抓取笔趣阁小说,并保存到本地TXT文件的更多相关文章

  1. Jsoup-基于Java实现网络爬虫-爬取笔趣阁小说

    注意!仅供学习交流使用,请勿用在歪门邪道的地方!技术只是工具!关键在于用途! 今天接触了一款有意思的框架,作用是网络爬虫,他可以像操作JS一样对网页内容进行提取 初体验Jsoup <!-- Ma ...

  2. bs4爬取笔趣阁小说

    参考链接:https://www.cnblogs.com/wt714/p/11963497.html 模块:requests,bs4,queue,sys,time 步骤:给出URL--> 访问U ...

  3. Python爬取笔趣阁小说,有趣又实用

    上班想摸鱼?为了摸鱼方便,今天自己写了个爬取笔阁小说的程序.好吧,其实就是找个目的学习python,分享一下. 1. 首先导入相关的模块 import os import requests from ...

  4. python应用:爬虫框架Scrapy系统学习第四篇——scrapy爬取笔趣阁小说

    使用cmd创建一个scrapy项目: scrapy startproject project_name (project_name 必须以字母开头,只能包含字母.数字以及下划线<undersco ...

  5. scrapycrawl 爬取笔趣阁小说

    前言 第一次发到博客上..不太会排版见谅 最近在看一些爬虫教学的视频,有感而发,大学的时候看盗版小说网站觉得很能赚钱,心想自己也要搞个,正好想爬点小说能不能试试做个网站(网站搭建啥的都不会...) 站 ...

  6. python入门学习之Python爬取最新笔趣阁小说

    Python爬取新笔趣阁小说,并保存到TXT文件中      我写的这篇文章,是利用Python爬取小说编写的程序,这是我学习Python爬虫当中自己独立写的第一个程序,中途也遇到了一些困难,但是最后 ...

  7. scrapy框架爬取笔趣阁

    笔趣阁是很好爬的网站了,这里简单爬取了全部小说链接和每本的全部章节链接,还想爬取章节内容在biquge.py里在加一个爬取循环,在pipelines.py添加保存函数即可 1 创建一个scrapy项目 ...

  8. 免app下载笔趣阁小说

    第一次更新:发现一个问题,就是有时候网页排版有问题的话容易下载到多余章节,如下图所示: 网站抽风多了一个正文一栏,这样的话就会重复下载1603--1703章节. 解决办法: 于是在写入内容前加了一个章 ...

  9. 笔趣阁小说 selenium爬取

    import re from time import sleep from lxml import etree from selenium import webdriver options = web ...

随机推荐

  1. 【慕课网实战】五、以慕课网日志分析为例 进入大数据 Spark SQL 的世界

    提交Spark Application到环境中运行spark-submit \--name SQLContextApp \--class com.imooc.spark.SQLContextApp \ ...

  2. JSON.parse()——Uncaught SyntaxError: Unexpected token \ in JSON at position 1

    背景:项目安全处理方面之一 ——对特殊字符进行编解码(后端编码,前端解码) 特殊字符: "    %22 \    %5C /    %2F &   %26 %   %25 '    ...

  3. B树/[oracle]connect BY语句

    读大神的书,出现很多没有见过的函数和便捷操作,特此记录 connect by 之前没有接触过,为了学习这个语句,先了解一下B树数据类型是最好的方法. [本人摘自以下博客] https://www.cn ...

  4. Centos7 网络报错Job for iptables.service failed because the control process exited with error code.

    今天在进行项目联系的时候,启动在待机的虚拟机,发现虚拟机的网络设置又出现了问题. 我以为像往常一样重启网卡服务就能成功,但是它却报了Job for iptables.service failed be ...

  5. UML顺序图知识点介绍(Sequence Diagram)

    消息 调用消息 调用(procedure call)消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息接受者放弃会返回控制 在Rational Rose(2016版本如图所示) 异步消息 异 ...

  6. 对js中闭包,作用域,原型的理解

    前几天,和朋友聊天,聊到一些js的基础的时候,有一种‘好像知道,好像又不不知道怎么讲的感觉’...于是捡起书,自己理一理,欢迎拍砖. 闭包 理解闭包首先要理解,js垃圾回收机制,也就是当一个函数被执行 ...

  7. [Postman]拦截器扩展(15)

    什么是拦截器 注意: Interceptor功能仅在我们的Postman Chrome应用程序中受支持,目前在Postman桌面应用程序中不可用.如果您希望我们的桌面应用程序中提供此功能,请在此处告知 ...

  8. 微信公众号接入之排序问题小记 Arrays.sort()

    微信公众号作为强大的自媒体工具,对接一下是很正常的了.不过这不是本文的方向,本文的方向公众号接入的排序问题. 最近接了一个重构的小项目,需要将原有的php的公众号后台系统,转换为java系统.当然,也 ...

  9. MySQL 报错ERROR 1054 (42S22): Unknown column 'plugin' in 'mysql.user'

    MySQL  我们在创建用户的时候,可能会遇到以下报错: ERROR 1054 (42S22): Unknown column 'plugin' in 'mysql.user' 说明mysq.user ...

  10. 寒假小软件开发记录06--apk生成

    先在strings.xml中修改了软件名称,再修改软件图标. 在Android模式下,进入Image Asset,进行图标的修改: android studio中,build->generate ...