Java批量下载书籍图片并保存为PDF的方法

这篇具有很好参考价值的文章主要介绍了Java批量下载书籍图片并保存为PDF的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

因为经常出差火车上没网、不方便电子书阅读器批注,需要从某网站上批量下载多本书籍的图片并自动打包成PDF文件。

分析

1、尝试获得图片地址,发现F12被禁
解决方法:使用Chrome浏览器,点击右上角三个点呼出菜单,选择“更多工具”->“开发者工具”
或者使用Ctrl+Shift+C、Ctrl+Shift+I
2、审查元素,发现图片地址非常有规律:
在class为side-image的div里有一个img,src是../files/mobile/1.jpg?220927153454,去掉后面的问号部分即可得到/files/mobile/1.jpg,通过观察,这本书一共有多少页就会有多少个.jpg文件
3、回到栏目页,可得到基目录,所以批量抓取的大致思路是从栏目页获得基目录,然后不断累加一个数,直到获得jpg时对方服务器报404错误,即可得到刚刚处理的那一页即最后一页。
4、如何从栏目页获得基目录呢?
经观察,每个page_pc_btm_book_body里都有两个a标签,第一个是图片,第二个是“在线阅读”按钮,但是需要翻页怎么办呢?所以需要建立一个变量收集它们,每翻一页,做一次收集。于是可以写如下收集函数:

let books=[]
function catchBook() {
  let links = document.getElementsByClassName("page_pc_btm_book_body");
  for (let i in links) {
    if(!links[i].children||links[i].children.length<2)continue;
    let title = links[i].children[0].title;
    let link = links[i].children[0].href;
    books.push({title,link})
  }
}

然后在浏览器里每翻一页,在控制台里执行一次catchBook,这样书名和基目录就都获得了。
5、如何把JSON导出来呢
在控制台里JSON.stringify(books),把结果复制出来,然后到网上随便找一个JSON转Excel的工具,转出来即可,然后注意把第一行当表头,数据复制到第二行开始。
6、最后一步就写个程序从Excel里读出数据,把图片都批量抓下来即可,下面就说说如何写程序来处理。

需要引的包

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>ooxml-schemas</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

从Excel到实体

先定义一个实体,这里我多加了一列type,表示类型,name就是从上面那个里面获得的title,link就是上面获得的link属性。

import lombok.Data;

@Data
public class Book {
    private String type;
    private String name;
    private String link;
}

然后写个ExcelReader

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ExcelReader {

    public static List<Book> readXlsxToList(String filePath) {
        List<Book> bookList = new ArrayList<>();

        try (FileInputStream fileInputStream = new FileInputStream(filePath);
             Workbook workbook = new XSSFWorkbook(fileInputStream)) {

            Sheet sheet = workbook.getSheetAt(0);
            Iterator<Row> rowIterator = sheet.iterator();

            // 获取表头(第一行)并转换为属性数组
            Row headerRow = rowIterator.next();
            String[] headers = getRowDataAsStringArray(headerRow);

            // 遍历每一行(从第二行开始)
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                Book book = new Book();

                // 遍历每个单元格,并根据属性名称设置对应的实体类属性值
                for (Cell cell : row) {
                    int columnIndex = cell.getColumnIndex();
                    if (columnIndex < headers.length) {
                        String headerValue = headers[columnIndex];
                        String cellValue = getCellValueAsString(cell);

                        setBookProperty(book, headerValue, cellValue);
                    }
                }

                bookList.add(book);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return bookList;
    }

    private static String[] getRowDataAsStringArray(Row row) {
        String[] rowData = new String[row.getLastCellNum()];
        for (Cell cell : row) {
            int columnIndex = cell.getColumnIndex();
            rowData[columnIndex] = getCellValueAsString(cell);
        }
        return rowData;
    }

    private static String getCellValueAsString(Cell cell) {
        String cellValue = "";
        if (cell != null) {
            switch (cell.getCellType()) {
                case STRING:
                    cellValue = cell.getStringCellValue();
                    break;
                case NUMERIC:
                    cellValue = String.valueOf(cell.getNumericCellValue());
                    break;
                case BOOLEAN:
                    cellValue = String.valueOf(cell.getBooleanCellValue());
                    break;
                case FORMULA:
                    cellValue = cell.getCellFormula();
                    break;
                default:
                    cellValue = "";
            }
        }
        return cellValue;
    }

    private static void setBookProperty(Book book, String propertyName, String propertyValue) {
        switch (propertyName) {
            case "type":
                book.setType(propertyValue);
                break;
            case "name":
                book.setName(propertyValue);
                break;
            case "link":
                book.setLink(propertyValue);
                break;
            // 添加其他属性
            default:
                // 未知属性,可以根据需要进行处理
                break;
        }
    }
}

从实体集合到批量下载成jpg

还需要想办法实现批量下载的功能,需要注意的是Windows的默认文件排序是按ASC码排序的,会把10.jpg排在2.jpg前面,所以需要对页码格式化一下,把它变成三位数。

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class ImageDownloader {

    public static void downloadImages(List<Book> bookList, String targetDir) {
        for (Book book : bookList) {
            String type = book.getType();
            String name = book.getName();
            String link = book.getLink();

            String basePath = targetDir + "/" + type + "/" + name;

            int count = 1;
            boolean continueDownload = true;

            if(!new File(basePath).exists()){
                new File(basePath).mkdirs();
            }
            while (continueDownload) {
                String imgUrl = link + "files/mobile/" + count + ".jpg";
                String outputPath = String.format("%s/%03d.jpg", basePath, count);

                if (!imageExists(outputPath)) {
                    try {
                        downloadImage(imgUrl, outputPath);
                        System.out.println("Downloaded: " + outputPath);
                    } catch (IOException e) {
                        System.out.println("Error downloading image: " + imgUrl);
                        e.printStackTrace();
                        continueDownload = false;
                    }
                } else {
                    System.out.println("Image already exists: " + outputPath);
                }

                count++;
            }
        }
    }

    private static boolean imageExists(String path) {
        Path imagePath = Paths.get(path);
        return Files.exists(imagePath);
    }

    private static void downloadImage(String imageUrl, String outputPath) throws IOException {
        URL url = new URL(imageUrl);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        int responseCode = httpConn.getResponseCode();

        if (responseCode == HttpURLConnection.HTTP_OK) {
            try (InputStream inputStream = httpConn.getInputStream();
                 FileOutputStream outputStream = new FileOutputStream(outputPath)) {

                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
        } else {
            throw new IOException("Server returned response code " + responseCode);
        }
    }
}

开始批量下载

import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<Book> books = ExcelReader.readXlsxToList("C:\\Users\\Administrator\\Desktop\\某某书库.xlsx");
        String targetDir = "D:\\书库\\";
        ImageDownloader.downloadImages(books, targetDir);
    }
}

写完执行,回去睡一觉

jpg图片批量转成pdf

都下载完之后,就可以想办法批量转成PDF格式了。

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;

public class ImageToPdfConverter {
    public static void convertToPdf(String folderPath, String outputFilePath) {
        try {
            // 获取文件夹中的所有jpg文件
            File folder = new File(folderPath);
            File[] files = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".jpg"));

            // 预读第一章图片获得大小
            Rectangle rect = null;
            if (files.length == 0) {
                return;
            } else {
                Image image = Image.getInstance(files[0].getAbsolutePath());
                rect = new Rectangle(image.getWidth(), image.getHeight());
            }

            // 创建PDF文档对象
            Document document = new Document(rect);
            document.setMargins(0, 0, 0, 0);
            // 创建PDF写入器
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputFilePath));
            writer.setStrictImageSequence(true);
            // 打开PDF文档
            document.open();

            // 遍历图片文件并将其加入到PDF文档中
            for (File file : files) {
                Image image = Image.getInstance(file.getAbsolutePath());
                document.add(image);
            }

            // 关闭PDF文档
            document.close();

            System.out.println("PDF文件生成成功!");
        } catch (FileNotFoundException | DocumentException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String startDir="D:\\书库\\开发技术\\";
        File[] subdirs = new File(startDir).listFiles();
        for (File subdir : subdirs) {
            if(subdir.isDirectory()){
                convertToPdf(subdir.getAbsolutePath(), subdir.getAbsolutePath()+".pdf");
            }
        }
    }
}

结束

最后把PDF文件传到网盘上,手机、平板、电脑随时可以下载离线看,非常舒服。

注意:自己抓取书籍自己看无所谓,但通过网络分享出去是侵犯他人著作权的。文章来源地址https://www.toymoban.com/news/detail-645479.html

到了这里,关于Java批量下载书籍图片并保存为PDF的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java Word转PDF(直接转和以图片形式转)、PDF转图片、图片转PDF

    在淘宝上找了一家写代码的店铺写了一个工具类,再参考网上的代码,改了改 用到的类库: 工具类代码:

    2024年02月12日
    浏览(44)
  • Java pdf转图片

    2024年02月12日
    浏览(42)
  • 【生成PDF】【JAVA】纯后台生成Echarts图片,并将图片生成到PDF文档

    目录 前言 一、如何后台生成Echarts图片? 1.PhantomJS 2.PhantomJS的下载  3.用phantomjs调用echarts-converts.js生成图片 二、Java如何将Echarts图生成到PDF 1.生成PDF依赖 2.Java代码测试例子:  3.测试结果   三、下载生成的PDF ReportFormUtil 提示:本文仅用于记录日常,多有不足,仅供参考。

    2024年02月09日
    浏览(46)
  • JAVA 实现PDF转图片(spire.pdf.free版)

    1. 引入 jar 包 导入方法1: 手动引入。将Free Spire.PDF for Java下载到本地,解压,找到lib文件夹下的Spire.PDF.jar文件。在IDEA中打开如下界面,将本地路径中的jar文件引入Java程序:  导入方法2:如果您想通过 Maven安装,则可以在 pom.xml 文件中添加以下代码导入 JAR 文件。 1 2 3 4 5

    2024年02月05日
    浏览(40)
  • Java实现图片转PDF

    某w*s图片转PDF还要收费,简直不讲武德!我啪的一下,很快啊,一段代码搞定! 引入pom依赖 工具类

    2024年01月15日
    浏览(58)
  • JAVA 实现PDF转图片格式

    依赖: pdf存放路径 正文开始: pdf转换多张图片、长图 展示效果: 附加:小程序预览wxml代码

    2024年02月06日
    浏览(43)
  • java中预览pdf或者图片

       

    2024年02月12日
    浏览(42)
  • pdf转图片【java版实现】

    引入需要导入到项目中的依赖,如下所示: pdf转图片的工具类如下所示,直接拷贝到项目即可 执行工具类中的main方法就行,会将pdf文件转换成多张图片到同级目录中。

    2024年02月13日
    浏览(41)
  • JAVA PDF 给PDF添加文字/图片水印(指定内容),并且设置位置

    提示:看完这个简单的demo 后就知道怎样去操作一个PDF了 文章目录 前言 一、前提准备 二、使用步骤 1.引入库 2.以下是部分代码的作用 总结 提示:操作PDF其实是一件很简单的事情,比一般的CRUD都简单 例如:我们拿到了一个需求,我需要给这个PDF设置一个 电子签名 ( 就是一

    2024年04月23日
    浏览(47)
  • 批量打印-----jsPDF将图片转为pdf,并合并pdf

    安装依赖并引入 注意一、 使用jspdf将图片(jpg/jpeg/png/bmp)转pdf(记为pdfA),得到的pdf(pdfA)和需要合并的pdf(记为pdfB)类型不一致,需要将pdfA转为pdfB类型,才能合并,使用arraybuffer转,具体如下 注意二、 jspdf 可转pdf的图片类型有jpg、jpeg、png、bpm, 不支持 tif 和 tiff 图片类

    2024年02月13日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包