1.进入小说网站http://www.147xs.org/

可以看到有非常多的小说,我们随便点进去一个

点进来就是小说的目录部分了,但我们最终解析的并不是目录,而是有内容的网页,点进:第一章 此间少年

这才是我们真正要爬取的网页
但是我们进入这种网页似乎费了点功夫,这样的页面我们称作二级页面,爬取二级页面首先需要在一级页面(也就是章节目录页面)得到二级页面的链接,后面讲代码实现时会具体说到
由于我们要爬取所有小说,所以一级页面不止一个,这些链接就在网站首页里,每个小说都是一个一级链接,所以只需要将首页的所有小说的链接都抓取到即可,之后再进入每个小说的链接获取所有章节的链接,进入每个章节爬取内容
这么多一级页面(小说章节目录页面)和二级页面(每个章节内容页面)我们怎么区分呢,究竟什么时候存入二级页面?什么时候爬取二级页面内容?
我们总不能该存页面的时候去爬,该爬页面的时候去存
所以要对每级的页面的url进行比对分析
http://www.147xs.org/book/13794/
http://www.147xs.org/book/13794/206911.html
点进去发现第一个为一级页面,第二个为二级页面
两者的最大区别就是有没有.html后缀
那么思路很清晰了,如果该url有.html后缀则进去爬内容,如果没有则在一级页面将二级页面链接加入请求队列之中,即存入二级页面
接下来是对url分析的代码

 public void process(Page page) {//得到url,起始为http://www.147xs.org/,首页String url=page.getUrl().get();//通过分析知道带有html的url是之前获取到的每个章节的链接。if(url.contains(".html")) {//如果是章节的链接则进入this.getContent(page);//抓取内容函数}else if(url.equals("http://www.147xs.org/")){//如果是网站首页则进入,获取所有小说的链接List<String> links = page.getHtml().links().regex(".*book/\\d+/").all();//正则匹配urlpage.addTargetRequests(links);//加入请求队列等待处理page.setSkip(true);//跳过保存管道类} else {//获取该小说的所有章节的链接List<String> links = page.getHtml().links().regex(".*\\d+\\.html").all();//正则匹配urlpage.addTargetRequests(links);//加入请求队列等待处理page.setSkip(true);//跳过保存管道类}}

分析如下
第一个if相信不用我说大家也能看懂,判断是否为二级页面的链接
如果是则进去爬内容,不是则再次判断
else if是为了判断是不是网站首页,如果是,则进入把一级页面的链接抓取下来加入到请求队列。这个else if在整个程序中只运行了一次,大家可以思考一下原因
else以上的都不是那么该页面所处的位置只能为一级页面了,所以将二级页面的链接抓取下来加入请求队列
请求队列这里我要交代一下
听他的名字就知道他是个队列,里面存放了你加入的url,只要队列中有url,那么刚才的process函数就会自动执行,并且是按照存入url的顺序执行的。具体为什么我们无需深究,框架自带的
比如我们初始进入的是网站首页,第一次执行了process函数后请求队列会加入很多的url
可能为(实际情况可能不会严格按照从小到大的顺序,随机抓取):
http://www.147xs.org/book/13794/
http://www.147xs.org/book/13795/
http://www.147xs.org/book/13796/
http://www.147xs.org/book/13797/
http://www.147xs.org/book/13798/
。。。。。。
执行完第一次后,请求队列中都是小说的链接,也就是一级页面的链接,
由于每次解析完一个页面,该页面的url就会出队列,所以网站首页地址没了
再次执行process,进入的页面为http://www.147xs.org/book/13794/
由于这个页面的url没有.html,则执行else,将每个章节的链接加入请求队列
执行完后请求队列变成
http://www.147xs.org/book/13795/
http://www.147xs.org/book/13796/
http://www.147xs.org/book/13797/
http://www.147xs.org/book/13798/
。。。。。。
http://www.147xs.org/book/66666/ 假设这个为最后一个小说的链接
http://www.147xs.org/book/13794/206911.html
http://www.147xs.org/book/13794/206912.html
http://www.147xs.org/book/13794/206913.html
http://www.147xs.org/book/13794/206914.html
。。。。。。。
可以看出需要等所有的一级页面全部解析完毕才能开始爬取二级页面
当然,如果你只想爬取一部小说,只需要将起始的url改为http://www.147xs.org/book/13794/(只是举例子)

爬取内容部分
首先要清楚自己需要爬什么(以《伏天氏》为例)
1.小说书名
2.章节标题
3.章节内容

首先是小说的书名

F12 开发者模式

小说书名的xpth://div[@class=‘con_top’]/a[3]/text()
得到伏天氏
同理

章节的xpth://div[@class=‘bookname’]/h1/text()
得到第一章 此间少年

内容

内容的xpth://div[@id=‘content’]//p/text() 注意这里的p有多个
最后的结果为所有内容
爬取内容代码如下

public void getContent(Page page){//书名String bookname=page.getHtml().xpath("//div[@class='con_top']/a[3]/text()").get();//标题String title=page.getHtml().xpath("//div[@class='bookname']/h1/text()").get();//内容List<String> all = page.getHtml().xpath("//div[@id='content']//p/text()").all();//通过键值对的方式存入,用于后面写入文件时用到这些属性page.putField("bookname",bookname);page.putField("title",title.replaceAll("[/?\\\\]",""));page.putField("content",all);}

.get表示取出标签里的文本(只能取一个),返回值为字符串
.all是由于p标签有多个,所以需要取出每个p标签里面的内容,最后返回的也是一个集合
由于后面需要bookname属性和title属性的值来创建文件,所以要防止属性值出现"/","\\","?"干扰文件路径
putField方法类似于Map,通过键值对保存数据
最后爬取的内容都会经过一个管道,默认是输出到控制台
但我们希望通过文件保存下来
这时候就要自己实现一个管道
代码如下

class SavePipeline implements Pipeline{@Overridepublic void process(ResultItems resultItems, Task task) {//通过key获取值String bookname=resultItems.get("bookname");String title = resultItems.get("title");List<String> contents=resultItems.get("content");//创建小说目录File file=new File("网络小说\\"+bookname);if(!file.exists()){file.mkdirs();}//写入文件try {FileOutputStream writer=new FileOutputStream(file.getAbsolutePath()+"\\"+title+".txt");//遍历集合,取出每段内容for (String content : contents) {String replace = content.replace("。", "\n");writer.write(replace.getBytes("utf8");}writer.flush();writer.close();} catch (Exception e) {e.printStackTrace();}}
}

上述的resultItems就是存入爬取的内容时所说的那个Map
通过get方法传入key,得到value
开始的process函数里有一个page.setSkip(true);//跳过保存管道类
可能大家有疑惑,这个函数是设置是否跳过管道,直接解析下一个url
由于我们的管道是保存爬取来的数据的,但是程序执行到page.setSkip(true)之前我们并没有爬取数据,如果不设置跳过管道,则会经过管道保存数据,此时出现空指针异常

后面的写入文件就不用多说了

接下来就是启动爬虫了
启动前需要配置一些参数
先配置Site
从第一行往下分别对应设置编码方式,设置超时时间,设置重试次数,设置循环次数
当然也不必配置这么多
个人认为在网速给力的时候只需要设置编码方式即可

接下来分析主函数里的配置

  1. new xioashuo()里面的xioashuo这个类就是实现了解析url的process函数的那个类,如果没看明白待会给出所有代码时你就懂了
  2. addurl为添加url,可以添加多次
  3. addPipeline(new SavePipeline()) 和*addPipeline(new ConsolePipeline())*添加管道,即处理数据的类,第一个是我们自己实现的
    而第二个是框架自己带的,如果一个管道都不添加则默认为第二个,会将结果打印到控制台;我们让他即保存到文件,有能输出到控制台
    4.thread开启多线程,本例中开启了50个线程同时爬取
    5.run启动爬虫
private Site site = Site.me().setCharset("utf8").setTimeOut(10000).setRetryTimes(5).setCycleRetryTimes(3);@Overridepublic Site getSite() {return site;}public static void main(String[] args) {String startUrl="http://www.147xs.org";Spider.create(new xioashuo()).addUrl(startUrl).addPipeline(new SavePipeline()).addPipeline(new ConsolePipeline()).thread(50).run();}

全部代码如下:
首先创建一个Maven工程并导入依赖

     <dependency><groupId>us.codecraft</groupId><artifactId>webmagic-core</artifactId><version>0.7.3</version></dependency><dependency><groupId>us.codecraft</groupId><artifactId>webmagic-extension</artifactId><version>0.7.3</version></dependency>
import us.codecraft.webmagic.*;
import us.codecraft.webmagic.pipeline.ConsolePipeline;
import us.codecraft.webmagic.pipeline.Pipeline;
import us.codecraft.webmagic.processor.PageProcessor;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;public class xioashuo implements PageProcessor {public void process(Page page) {String url=page.getUrl().get();//得到url,起始为http://www.147xs.org///通过分析知道带有html的url是之前获取到的章节的链接。if(url.contains(".html")) {//如果是章节的链接则进入this.getContent(page);//抓取内容函数}else if(url.equals("http://www.147xs.org/")){//如果是网站首页则进入,获取所有小说的链接List<String> links = page.getHtml().links().regex(".*book/\\d+/").all();page.addTargetRequests(links);page.setSkip(true);} else {//获取该小说的所有章节的链接List<String> links = page.getHtml().links().regex(".*\\d+\\.html").all();page.addTargetRequests(links);page.setSkip(true);}}public void getContent(Page page){//书名String bookname=page.getHtml().xpath("//div[@class='con_top']/a[3]/text()").get();//标题String title=page.getHtml().xpath("//div[@class='bookname']/h1/text()").get();//内容List<String> all = page.getHtml().xpath("//div[@id='content']//p/text()").all();//通过键值对的方式存入,用于后面写入文件时用到这些属性page.putField("bookname",bookname);page.putField("title",title.replaceAll("[/?\\\\]",""));page.putField("content",all);}private Site site = Site.me().setCharset("utf8").setTimeOut(10000).setRetryTimes(5).setCycleRetryTimes(3);public Site getSite() {return site;}public static void main(String[] args) {String startUrl="http://www.147xs.org/";Spider.create(new xioashuo()).addUrl(startUrl).addPipeline(new SavePipeline()).addPipeline(new ConsolePipeline()).thread(50).run();}
}/*** 自定义管道类* 用于保存爬取的小说到文件*/
class SavePipeline implements Pipeline{public void process(ResultItems resultItems, Task task) {//通过key获取值String bookname=resultItems.get("bookname");String title = resultItems.get("title");List<String> contents=resultItems.get("content");//创建小说目录File file=new File("网络小说\\"+bookname);if(!file.exists()){file.mkdirs();}//写入文件try {FileOutputStream writer=new FileOutputStream(file.getAbsolutePath()+"\\"+title+".txt");//遍历集合,取出每段内容for (String content : contents) {String replace = content.replace("。", "\n");writer.write(replace.getBytes(StandardCharsets.UTF_8));}writer.flush();writer.close();} catch (Exception e) {e.printStackTrace();}}
}

运行一下

开始时先存入每个小说链接
等到所有小说的章节链接爬取完后
开始爬取每部小说


剩下的就是耐心等待了

如果你只想爬取一部小说
只需要在主函数里将startUrl改成你想要爬取的小说的链接(但只能是
http://www.147xs.org/这个网站下的)
例如我只想爬取
《盗墓笔记》
这是他的url:http://www.147xs.org/book/3505/



大功告成!!!

如果有疑问可以评论区留言,感谢阅读

WebMagic爬取小说网站所有小说相关推荐

  1. Python3爬取豆瓣网站奇幻小说信息

    目的:爬取豆瓣网站的奇幻小说信息 **分析:**URL=https://book.douban.com/tag/%E5%A5%87%E5%B9%BB?start=0&type=T,通过手动翻页 ...

  2. Python爬取小说网站下载小说

    1前言 这个小程序是用来爬取小说网站的小说的,一般的盗版小说网站都是很好爬取的 因为这种网站基本没有反爬虫机制的,所以可以直接爬取 该小程序以该网站http://www.126shu.com/15/下 ...

  3. 爬取笔趣阁小说网站上的所有小说(二)

    爬取笔趣阁小说网站上的所有小说(二) 网址为:https://www.biqukan.cc/topallvisit/1.html 我们已经拿到了所有小说的地址爬取笔趣阁小说网站上的所有小说(一),现在 ...

  4. 爬虫实战--简单爬取小说网站的小说(面对过程)

    本篇博文为简单爬取小说网站的小说代码分为三种编程思想,面对过程,面对函数,面对对象,本篇为第一种,也是最简单的一种.面对过程即已过程为中心的编程思想.这里我们把爬取的详细分为以下几个步骤: 1.下载小 ...

  5. Python网络爬虫(九):爬取顶点小说网站全部小说,并存入MongoDB

    前言:本篇博客将爬取顶点小说网站全部小说.涉及到的问题有:Scrapy架构.断点续传问题.Mongodb数据库相关操作. 背景: Python版本:Anaconda3 运行平台:Windows IDE ...

  6. 爬取笔趣阁小说网站上的所有小说(一)

    爬取笔趣阁小说网站上的所有小说(一) 网址为:https://www.biqukan.cc/topallvisit/1.html 反反爬虫 爬虫首先要做的就是看看目标网址有没有反爬虫手段,一般网站都是 ...

  7. python爬取小说网站_Python爬取小说网站下载小说

    1前言 这个小程序是用来爬取小说网站的小说的,一般的盗版小说网站都是很好爬取的 因为这种网站基本没有反爬虫机制的,所以可以直接爬取 该小程序以该网站http://www.126shu.com/15/下 ...

  8. 初次尝试python爬虫,爬取小说网站的小说。

    本次是小阿鹏,第一次通过python爬虫去爬一个小说网站的小说. 下面直接上菜. 1.首先我需要导入相应的包,这里我采用了第三方模块的架包,requests.requests是python实现的简单易 ...

  9. python3+正则(re)增量爬虫爬取笔趣阁小说( 斗罗大陆IV终极斗罗)

    python3+re 爬虫爬取笔趣阁小说 斗罗大陆IV终极斗罗 爬取前准备 导入的模块 分析 正则的贪婪与非贪婪 附完整代码示例 爬取前准备 导入的模块 import redis #redis数据库 ...

  10. python爬取小说爬取_用python爬取笔趣阁小说

    原标题:用python爬取笔趣阁小说 首先打开笔趣阁网址,链接,搜索自己想要的小说. 在网站内单击右键,点击检查,会出现如下界面! 我们需要的章节信息就在我划的这块, 可以将每个标签点一下,它对应的内 ...

最新文章

  1. 一个中年程序员遇到突发情况的一些胡言乱语
  2. ASP.NET MVC使用Oauth2.0实现身份验证
  3. 计算机考研高分扎堆学校如何处理,考研:名校400+扎堆,450+和数学满分频现,网友:这届太厉害了!...
  4. hudi延迟日志命名
  5. Feisty中totem-xine播放rm和rmvb没有声音
  6. react里 MD5加密
  7. 《长安十二时辰》带来的启示:行走江湖,数据泄露怎能不防?
  8. 更换tomcat 地址栏图标
  9. 怎样批量将图片转成PDF格式?图片转换PDF操作方法
  10. 在Excel中如何把每三行数据合并为一行?
  11. JAVA计算机毕业设计教育培训机构信息管理系统Mybatis+系统+数据库+调试部署
  12. 戴尔笔记本插耳机听歌暂停后继续声音突然变大
  13. group python 读hdf5_HDF5 文件及 h5py
  14. 论文阅读之《Color Constancy Using CNNs》
  15. 浏览器手动设置Cookie
  16. 学习云计算怎么样?未来10年云计算发展前景如何?
  17. AK5703的ALC
  18. php中文网11期录播资源下载,PHP中文网原创视频提供下载啦!
  19. 计算机毕业设计Java高校排课管理系统(源码+系统+mysql数据库+lw文档)
  20. 电信 IPRAN 设备组网方案_面向产业互联网业务承载网解决方案探讨

热门文章

  1. ggplot2设置坐标轴范围_6.6 坐标轴:设置坐标轴上刻度的显示位置
  2. Banner图片轮播器实现ViewPager图片切换效果及下方小圆点
  3. 单片机复位电路是怎么工作的?
  4. Linux命令总结归纳
  5. 14年macmini装双硬盘_苹果2014款Mac mini更换固态硬盘图文教程
  6. 网站卡死服务器2008,winserver2008r2频繁卡死?
  7. 不朽的浪漫网站服务器,浪漫人族TOD专访 虫族强大让我震惊
  8. 企业erp系统服务器,ERP系统是什么
  9. 【搜索/tarjan找环】zznu-简单环路
  10. 计算机组成原理期末知识点复习及考点总结