软件园学生在线

  • {{ item.name }}
  • 2023试用期

登录与注册

【后端二】王春雨

  • 王春雨
  • 2022-10-22
  • 1

前言:感动,至少我完成的很满意了/(ㄒoㄒ)/~~

我们首先看一下效果吧
运行后,我们根据提示输入1或者2及要爬取小说的网址

若有人看不见示例(我们不推荐这样的用户使用/(ㄒoㄒ)/,会自动补全网址):
爬取完的小说会格式完美的以markdown的形式保存



本次作业中遇到了很多问题,都成功找到了解决方法/★,°:.☆( ̄▽ ̄)/$:.°★
总结如下:

1.章节网址

起初我将示例网址直接换成了本次作业要求的小说网站的网址,发现总是出现如图所示的报错

后来发现问题出现在每章的网址上,这使得访问的网址总是404不存在。



也就是说在本小说网站中,每章的网址并不如课上实例展示的为

menuUrl+subLink

而应改为

"https://www.aixiaxsw.com"+subLink

2.获取标题、作者

 String title = document.body().selectFirst("h1").text();
 String author = document.body().selectFirst("p").text();
 fileOut.write(("### "+title+"\n\n").getBytes());
 fileOut.write(("<b>"+author+"</b>"+"\n\n").getBytes());

在这里给标题加了h3标题的格式,作者名字加粗了

3.获取目录

System.out.println("正在爬取目录,请稍后...");
        int count1 = 1,num=1;
        //循环操作每个章节
        for (Element a : as) {
            if (count1 <= 9) {
                count1++;
                continue;
            }
            String subLink = a.attr("href");
            String chapterName = a.text();
            Document chapter = null;
            try {
                chapter = Jsoup.connect("https://www.aixiaxsw.com"+subLink).get();
            } catch (IOException ewww) {
                ewww.printStackTrace();
            }

            fileOut.write(( "<a href="+"\""+"#"+num+"\">"+chapterName +"</a>"+"<br>").getBytes());
            num++;
        }
        System.out.println("目录爬取完毕!");

在爬取目录时加上了页面内跳转的功能

4.跳过最新章节爬取正文章节


我们会发现该小说网站会有9章的最新章节放在最前面,而他们都是在相同的html标签下,我们这里采用了一个小小的计数器。

for (Element a : as) {
            if (count1 <= 9) {
                count1++;
                continue;
            }

跳过前9个章节

5.小说格式

这是做的较为粗糙的一个部分,按照上课讲的内容我们是以这种方式获取的正文

Elements chapterContent = chapter.select("#content");

经过查询,我没找到在这基础上保存格式的方法,但经过观察,小说分段有原则,以。”为结尾即会分段,所以我们把这个问题简化为遇到这些分段并添加段前空格即可。
所以添加亿些些细节,我们得到了如下代码 ↓

Elements chapterContent = chapter.select("#content");
String str1=chapterContent.text().replace("。","。<br>        ");
String str2=str1.replace("!","!<br>        ");
String str3=str2.replace("\"","\"<br>        ");
String Str=str3.replace("?","?<br>        ");
fileOut.write(("\n\n" +"<b> "+chapterName + "</b>"+ "<p id=\""+num+"\">"+"<br>"+"         "+Str+"</p>").getBytes());
num++;

同时在这段代码中也细节的将每章标题加粗了。

最后放代码↓

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.*;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import org.jsoup.safety.Cleaner;

public class Spider {
    public static void main(String[] args) throws IOException {

        //确定网址
        String menuUrl = "https://www.aixiaxsw.com/114/114350/";//默认目录页
        final String fileAddr = "./";
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入1则爬取示例小说《不婚主义前男友总想骗我结婚》,输入2则根据下次输入爬取");
        if(scanner.nextInt()==2) {
            System.out.println("请输入网址,示例:https://www.aixiaxsw.com/114/114350/");
            menuUrl = scanner.next();
            boolean www=menuUrl.contains("www.");
            if(!www){
                menuUrl="www."+menuUrl;
            }
            boolean http=menuUrl.contains("https://");
            if(!http){
                menuUrl="https://"+menuUrl;
            }
            boolean a=menuUrl.endsWith("/");
            if(!a){
                menuUrl=menuUrl+"/";
            }

        }
        System.out.print("您要爬取的小说网址为"+menuUrl);

        // 获取文档对象
        Document document = null;
        try {
            Connection con = Jsoup.connect(menuUrl).userAgent(
                            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
                    .timeout(30000); // 设置连接超时时间

            Connection.Response response = con.execute();

            if (response.statusCode() == 200) {
                document = con.get();
            } else {
                System.out.println(response.statusCode());
                return;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        String title = document.body().selectFirst("h1").text();
        System.out.println("开始爬取:"+title);
        String author = document.body().selectFirst("p").text();
        Elements menu = document.body().select("div[id=list]").select("dl dd");
        Elements as = menu.select("a[href]");

        System.out.println("小说将保存在:"+fileAddr + title+".md  中");
        File file = new File(fileAddr + title+".md");
        OutputStream fileOut = null;
        try {
            fileOut = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 在向文件中输出每一章节前,先输出小说名和作者名
        fileOut.write(("### "+title+"\n\n").getBytes());
        fileOut.write(("<b>"+author+"</b>"+"\n\n").getBytes());

        System.out.println("正在爬取目录,请稍后...");
        int count1 = 1,num=1;
        //循环操作每个章节
        for (Element a : as) {
            if (count1 <= 9) {
                count1++;
                continue;
            }
            String subLink = a.attr("href");
            String chapterName = a.text();
            Document chapter = null;
            try {
                chapter = Jsoup.connect("https://www.aixiaxsw.com"+subLink).get();
            } catch (IOException ewww) {
                ewww.printStackTrace();
            }

            fileOut.write(( "<a href="+"\""+"#"+num+"\">"+chapterName +"</a>"+"<br>").getBytes());
            num++;
        }
        System.out.println("目录爬取完毕!");

        int count = 1;
        num=1;

        //循环操作每个章节
        for (Element a : as) {
            if (count <= 9) {
                count++;
                continue;
            }
            String subLink = a.attr("href");
            String chapterName = a.text();
            System.out.println("当前爬取章节:"+chapterName);
            Document chapter = null;
            try {
                chapter = Jsoup.connect("https://www.aixiaxsw.com"+subLink).get();
            } catch (IOException ewww) {
                ewww.printStackTrace();
            }
            Elements chapterContent = chapter.select("#content");

            String str1=chapterContent.text().replace("。","。<br>        ");
            String str2=str1.replace("!","!<br>        ");
            String str3=str2.replace("\"","\"<br>        ");
            String Str=str3.replace("?","?<br>        ");
            fileOut.write(("\n\n" +"<b> "+chapterName + "</b>"+ "<p id=\""+num+"\">"+"<br>"+"         "+Str+"</p>").getBytes());
            num++;
        }

        System.out.println("小说爬取完成");
        fileOut.close();
    }
}

成就感拉满————————
注:拿《不婚主义前男友总想骗我结婚》当示例小说主要是因为它短!!与个人癖好没有任何关系!!

再注:我一开始爬的几千章的小说,Typora显示文件太大打不开,也没有很大吧呜呜呜

王春雨
王春雨
© 2025 软件园学生在线
Theme by Wing