昨天小编看到了一部不错的小说,但是没有办法下载,只能一页一页地看,于是想到了爬虫,现在Java也有了爬虫的框架,很简单,就算小白也能轻易入门,话不多说,直接上手。
1.首先引入相关依赖
不会maven的话可以按照右边直接去maven库下载添加jar包,注意不要少包,否则会报找不到类
依赖示例代码:
<dependencies><dependency><groupId>us.codecraft</groupId><artifactId>webmagic-core</artifactId><version>0.7.5</version></dependency></dependencies>
2.新建类,实现 PageProcessor 接口,重写两个方法
3.设置爬取文件配置属性,在 getSite 方法返回
site对象的方法是方法链,可以连着设置很多属性,具体说几个重要的
//设置带爬取文件的相关配置private final Site site = Site.me() // 返回Site对象,必须的.setCharset("utf-8") //设置爬取网页字符集,有些网页是gbk.setTimeOut(1000) //设置超时时间.setSleepTime(1000); //设置休眠时间
4.添加main方法
public static void main(String[] args) {// Spider.create(new FictionDownload()).thread(1).addUrl("").run(); 这个基本是固定写法// thread(int threadNum)开启多少个线程执行 addUrl(String... urls) 爬取网页的地址,如果是小说,一般是章节目录,用来初始化,但我用的第一章地址Spider.create(new FictionDownload()).thread(1).addUrl("https://www.xbiquge.la/93/93746/35799191.html").run();}
当 Spider.create(...)...run()执行的时候,重写的 process() 方法就会执行
5.添加持久化属性和方法
// 小说名private String title;//内容集合List<String> content = new ArrayList<>();/*** 自定义方法,用来持久化数据* @param content 文本数据*/private void downBook(List<String> content) {//判断目录存不存在File file = new File("G:/Fiction");if (!file.exists()) {//如果不存在目录,则创建目录boolean mkdirs = file.mkdirs();}PrintWriter pw = null; //使用IO流try {//存为txt文件及其路径FileOutputStream fos = new FileOutputStream("G:/Fiction/" + title + ".txt");pw = new PrintWriter(fos, true);for (String string : content) {pw.println(string); // "\r\n" 换行}} catch (FileNotFoundException e) {e.printStackTrace();} finally {if (pw != null) {pw.close();//关流}}
这个就不多说,两个属性一个是爬取网页保存的书名,一个是数据,方法是用来保存持久化数据的
6.分析爬取网站的属性,F12打开网页元素控制台,有些浏览器按键可能不同
记住这些需要的元素标签和 id 或 class ,我们要获取他们的内容或属性
7.编写 process 方法,获取具体的数据
/*** Spider.create(new FictionDownload()).thread(1).addUrl("").run() 的时候会自动调用一次这个方法* page.addTargetRequests(List<String> urls) 添加待爬虫队列 数组* page.addTargetRequest(String requestString) 添加待爬虫队列 单条** @param page 当前的页面*/@Overridepublic void process(Page page) {//获取当前读取的 URLSelectable table = page.getUrl();Html html = page.getHtml();//获取当前页面if (table.toString().equals("https://www.xbiquge.la/93/93746/")) {// 如果当前链接是 首页 就会返回 true,进入这里// 这里我用的章节首页,小说最后一章完成会自动跳转到这里,做一些结尾的事情//获取书名title = html.xpath("[@id='info']/h1/text()").toString();downBook(content);} else {//获取章节名String chapter = html.xpath("[@class='bookname']/h1/text()").toString();//获取文章内容 [@id='content'] id为 content 的全部内容包括标签 /text() 获取文本List<String> temp = html.xpath("[@id='content']").all();// 对文章内容提纯处理String br = " <br> \n" +" <br> ";String[] split = temp.get(0).split(br);split[0] = split[0].substring("<div id=\"content\">\n".length() +" ".length());split[split.length - 1] = split[split.length - 1].substring(0, split[split.length - 1].length() - 6);content.add(chapter + "\n\n\n");content.addAll(Arrays.asList(split));// 获取下一章链接,并添加到爬虫队列String url = html.xpath("[@class='bottem1']/a[4]/@href").toString();page.addTargetRequest(url);System.out.println("已为当前队列添加:" + url + "链接!");}}
html.xpath()可以获取页面的属性或内容 html.xpath("[@id='content']").all()获取id为content的所有内容,包括下面的子标签html.xpath("[@class='bookname']/h1/text()")获取class为bookname的标签下h1标签下的文本html.xpath("[@class='bottem1']/a[4]/@href")获取class为bottem1的下第四个a标签下的href属性page.addTargetRequest(url);//添加单条待爬虫队列注:爬取网站我看了一下,最后一章再点下一页是退回小说章节目录,所有我加了一个判断,如果当前页面是章节目录,就说明最后一章结束,执行自定义方法保存数据,如果不是,则获取下一页链接,添加到爬取队列。
8.测试
9.爬取成功 ,附上所有代码
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.Selectable;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** @author 童年* @date 2021-12-29 18:35*/
public class FictionDownload implements PageProcessor {//设置带爬取文件的相关配置private final Site site = Site.me().setCharset("utf-8") //设置字符集.setTimeOut(1000) //设置超时时间.setSleepTime(1000); //设置休眠时间@Overridepublic Site getSite() {return site;}// 小说名private String title;//内容集合List<String> content = new ArrayList<>();/*** Spider.create(new FictionDownload()).thread(1).addUrl("").run() 的时候会自动调用一次这个方法* page.addTargetRequests(List<String> urls) 添加待爬虫队列 数组* page.addTargetRequest(String requestString) 添加待爬虫队列 单条** @param page 当前的页面*/@Overridepublic void process(Page page) {//获取当前读取的 URLSelectable table = page.getUrl();Html html = page.getHtml();//获取当前页面if (table.toString().equals("https://www.xbiquge.la/93/93746/")) {// 如果当前链接是 首页 就会返回 true,进入这里// 这里我用的章节首页,小说最后一章完成会自动跳转到这里,做一些结尾的事情//获取书名title = html.xpath("[@id='info']/h1/text()").toString();downBook(content);} else {//获取章节名String chapter = html.xpath("[@class='bookname']/h1/text()").toString();//获取文章内容 [@id='content'] id为 content 的全部内容包括标签 /text() 获取文本List<String> temp = html.xpath("[@id='content']").all();// 对文章内容提纯处理String br = " <br> \n" +" <br> ";String[] split = temp.get(0).split(br);split[0] = split[0].substring("<div id=\"content\">\n".length() +" ".length());split[split.length - 1] = split[split.length - 1].substring(0, split[split.length - 1].length() - 6);content.add(chapter + "\n\n\n");content.addAll(Arrays.asList(split));// 获取下一章链接,并添加到爬虫队列String url = html.xpath("[@class='bottem1']/a[4]/@href").toString();page.addTargetRequest(url);System.out.println("已为当前队列添加:" + url + "链接!");}}/*** 自定义方法,用来持久化数据* @param content 文本数据*/private void downBook(List<String> content) {//判断目录存不存在File file = new File("G:/Fiction");if (!file.exists()) {//如果不存在目录,则创建目录boolean mkdirs = file.mkdirs();}PrintWriter pw = null; //使用IO流try {//存为txt文件及其路径FileOutputStream fos = new FileOutputStream("G:/Fiction/" + title + ".txt");pw = new PrintWriter(fos, true);for (String string : content) {pw.println(string); // "\r\n" 换行}} catch (FileNotFoundException e) {e.printStackTrace();} finally {if (pw != null) {pw.close();//关流}}}public static void main(String[] args) {// Spider.create(new FictionDownload()).thread(1).addUrl("").run(); 这个基本是固定写法// thread(int threadNum)开启多少个线程执行 addUrl(String... urls) 爬取网页的地址,如果是小说,一般是章节目录,用来初始化,但我用的第一章地址Spider.create(new FictionDownload()).thread(1).addUrl("https://www.xbiquge.la/93/93746/35799191.html").run();}
}
10.创作不易,装载请注明出处。如果此文章对您有帮助,麻烦点个赞,收藏加关注,谢谢!