Java简单爬虫

Java简单爬虫

这篇文章主要是记录近期学习的内容和自己的一些理解,可能不是很全面或者不够严谨。欢迎大家讨论学习。

了解过爬虫的应该都知道,爬虫的原理是获取网页代码,分析其结构,通过URL等资源定位,将目标与我们程序建立连接,最后操作目标资源或下载到本地。

以下是我对某漫画网站写的java爬虫程序,主要功能是将网页上的漫画资源下载到本地。如有不便请联系删除。

这次的简单爬虫,用到了一个jsoup。导包:

<dependencies>
<!--        爬视频可以用tika-->
<!--        解析网页-->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.10.2</version>
        </dependency>
    </dependencies>

首先是漫画(Book)类:

package com.xuan.pojo;

import java.util.HashMap;
import java.util.Map;

//封装漫画类
public class Book {
    private String bid;
    private String  bname;
    private Map<String,String> chapter=new HashMap<String, String>();//用以记录某漫画的目录章节名称及其id

    public String getBid() {
        return bid;
    }

    public void setBid(String bid) {
        this.bid = bid;
    }

    public void setChapter(String chaptername,String chapterid){
        this.chapter.put(chaptername,chapterid);
    }

    public Map<String,String> getChapter(){
        return this.chapter;
    }

    public String getBname() {
        return bname;
    }

    public void setBname(String bname) {
        this.bname = bname;
    }

    @Override
    public String toString() {
        return "Book{" +
                "bid='" + bid + '\'' +
                ", bname='" + bname + '\'' +
                ", chapter=" + chapter +
                '}';
    }
}

然后是最重要的工具类(这里我把网站域名改为*,不影响程序的阅读与理解):

package com.xuan.utils;

import com.xuan.pojo.Book;
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.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;

public class HtmlParseUtil {

    //通过id获取该漫画的简单信息和目录。并返回Book对象。
    public Book bookInfo(String bid){
        //
        Book book=null;
        try {
            //目标网页的URL
            String url="https://******/"+bid+"/";
            //jsoup可以通过目标网页的URL返回一个DOM,从而像操作js代码一样,操作对象。
            Document document = Jsoup.parse(new URL(url), 30000);

            //获取漫画书的名字并创建对象
            book = new Book();
            //通过class找到使用过该class的所有对象,可能有多个用.get()可以按顺序获取,从零开始。
            // 此处的class用以修饰当前漫画的名字有且仅有一个。
            Elements ebname = document.getElementsByClass("comic-title j-comic-title");
            book.setBid(bid);
            book.setBname(ebname.text());

            //同理获取当前漫画的目录列表的对象,此处有且仅有一个。
            Elements el = document.getElementsByClass("chapter__list-box clearfix hide");
            //获取列表对象下的所有li对象。
            Elements elements = el.get(0).getElementsByTag("li");
            //遍历所有li对象获取目录中每一章的名字及其id,并赋值到book的chapter中。
            for (Element e:elements){
                String chapterid=e.getElementsByTag("a").attr("data-chapterid");
                String chaptername=e.getElementsByTag("a").text();
                book.setChapter(chaptername,chapterid);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return book;
    }

    //通过输入对象,获取漫画对象的信息,并下载到本地。
    // 该方法的主要作用是整理出每一章对应的新的URL,下载调用了重载的方法。
    public void download(Book book) throws IOException {
        String bid=book.getBid();
        String bname=book.getBname();
        Map<String, String> chapter = book.getChapter();
        //遍历对象中的目录信息chapter,并把每一章下载
        String key = null;
        String value = null;
        Iterator it = chapter.entrySet().iterator();

        while (it.hasNext()){
            Map.Entry entry = (Map.Entry) it.next();
            key = (String) entry.getKey();
            value = (String) entry.getValue();
            System.out.println("key:" + key + "---" + "value:" + value);

            //某一章的地址
            URL url=new URL( "https://******/"+bid+"/"+value+".html");
            download(url,bname,key);

        }
    }

    //通过URL 下载资源,并存到目标目录中(bname和chaptername用于拼接下载的目标路径)。
    public void download(URL url,String bname,String chaptername) throws IOException {
        //通过url获取当前章的DOM
        Document document = Jsoup.parse(url, 30000);
        //获取图片列表的URL
        //此处的的elements是每张图片的父级容器的和。
        Elements elements = document.getElementsByClass("rd-article-wr clearfix").get(0).getElementsByClass("rd-article__pic hide");
        //打印该章节有多少张目标图片
        System.out.println(elements.size());
        //循环下载。
        for (int i=0;i<elements.size();i++){
            //获取图片资源的有效地址
            String datasrc = elements.get(i).getElementsByTag("img").attr("data-src");
            URL dataurl=new URL(datasrc);
            //与资源建立链接
            HttpURLConnection urlConnection = (HttpURLConnection) dataurl.openConnection();
            //获取当前图片的输入流
            InputStream is = urlConnection.getInputStream();
            //指定文件输出路径
            File file = new File("cartoon/"+bname+"/"+chaptername+"/"+(i+1)+".jpg");
            //判断文件路径是否存在,不存在就新建。
            if(!file.getParentFile().exists()){
                boolean result = file.getParentFile().mkdirs();
                if(!result){
                    throw new RuntimeException("创建文件路径失败");
                }
            }
            //初始化输出流
            FileOutputStream fos = new FileOutputStream(file);
            //3.操作流
            byte[] buffer=new byte[1024];
            int len;
            while ((len=is.read(buffer))!=-1){
                fos.write(buffer,0,len);
            }
            //4.关闭流
            fos.close();
            is.close();
            urlConnection.disconnect();
        }
    }
}

运行主程序:

package com.xuan;

import com.xuan.pojo.Book;
import com.xuan.utils.HtmlParseUtil;
import java.io.IOException;
import java.net.URL;

public class Application {
    public static void main(String[] args) {
        HtmlParseUtil htmlParseUtil = new HtmlParseUtil();
        Book book = htmlParseUtil.bookInfo("215815");
        System.out.println(book);
        try {
            htmlParseUtil.download(book);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

Book{bid='215815', bname='进击的海王', chapter={第2话 老婆这是我送你的见面礼=921125, 番外 双节快乐!=921224, 预告 论海王的实战经验=919690, 第1话 妹子都是我的!=921067, 第3话 你敢动我老婆?=922853}}
key:第2话 老婆这是我送你的见面礼---value:921125
50
key:番外 双节快乐!---value:921224
7
key:预告 论海王的实战经验---value:919690
15
key:第1话 妹子都是我的!---value:921067
54
key:第3话 你敢动我老婆?---value:922853
57

输出的文件路径:
在这里插入图片描述

以上便是所有的代码以及运行结果,至于为什么用书的id而不是名字,这其实无所谓,只要能创建出book对象,已经构建出后续的URL,并没有太大影响。程序写的稍微简陋以及偷懒,仅供大家参考。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值