数据存储方式之 Excel

网络爬虫爬取的少量数据,可以使用 Excel 进行存储。本篇将主要讲解如何使用 Java 操作 Excel,具体包括 Excel 数据的读取以及 Excel 数据的写入。

在 Java 中主要涉及到两款操作 Excel 的工具:Jxl 以及 Apache 旗下的 POI 工具。本篇将主要介绍这两个工具的使用,并给出具体的网络爬虫实战案例。

Jxl 的使用

Jxl 是一款常用的 Java 操作 Excel 的 API,但其只对 .xls 有效,对2007版本以上的 Excel(.xlsx) 很难处理。在网络爬虫项目中,经常涉及到的是创建工作簿及工作表、写入 Excel 文件、读取 Excel 文件内容等操作,这也是本篇介绍的主要内容。关于其他方面的操作(如插入图片、调整宽高度、颜色设置等)读者可自行学习。在使用 Jxl 之前,需要在 Maven 工程的 pom.xml 文件中,配置所需 Jar 包,代码如下:

<!-- https://mvnrepository.com/artifact/net.sourceforge.jexcelapi/jxl -->
<dependency>
    <groupId>net.sourceforge.jexcelapi</groupId>
    <artifactId>jxl</artifactId>
    <version>2.6.12</version>
</dependency>

Jxl 数据写入
写入 Excel 文件之前,需要创建 Excel 工作簿及工作表,在 Jxl 中使用如下语句:

File xlsFile = new File("data/a.xls");
// 创建一个工作簿
WritableWorkbook workbook = Workbook.createWorkbook(xlsFile);
// 创建一个工作表
WritableSheet sheet = workbook.createSheet("sheet1", 0);

创建完工作表之后,便可以向数据表中添加数据,在 Jxl 中使用 addCell() 方法。具体操作如下:

//添加表头
sheet.addCell(new Label(0, 0, "post_id"));
sheet.addCell(new Label(1, 0, "post_title"));

Label 中的第一个数字表示列,第二个数字表示行,如上面的操作是对第一行的第一列和第二列分别添加的字符是 post_id 和 post_title。表头操作完毕后,便可以添加具体内容,具体操作如下:

//添加内容
for(int i = 0; i < 2; i++){
    sheet.addCell(new Label(0, i+1, "0" + i));
    sheet.addCell(new Label(1, i+1, "内容" + i));
}

之后,便可以执行写入文件操作,并关闭资源,释放内存:

//执行写入操作
workbook.write();
//关闭资源,释放内存
workbook.close();

通过上述一系列的操作,可成功将表头以及数据写入 Excel 中。
在这里插入图片描述
Jxl 数据读取
使用 Jxl 读取 Excel 文件(.xls)需要构造文件输入流,即确定所要读的是哪个 Excel 文件,具体操作方式如下:

//构造Excel文件输入流
String path = "data/a.xls";
InputStream is = new FileInputStream(path);

接着,需要声明工作簿以及具体需要读取的工作表:

// 声明工作簿
Workbook book  = Workbook.getWorkbook(is);
//获取名称为sheet1的表格,也可使用getSheet(0)获取第一个工作表
Sheet sheet = book.getSheet("sheet1");

从上面可以看出获取工作表的方式有两种,一种是直接使用工作表名 getSheet(String sheetName),另外一种是使用表格索引 getSheet(int arg)。接着,获取工作表中的总行数以及总列数,并利用循环得到数据,具体操作如下:

//获取工作表中的总行数及总列数
int rows = sheet.getRows();
int columns = sheet.getColumns();
//行列循环获取数据
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {
        //使用getCell方法读取数据,第一个是指定第几列,第二个参数才是指定第几行
        Cell cell= sheet.getCell(j,i);
        System.out.print(cell.getContents() + "\t");
    }
    System.out.println();
}

基于这些操作,便可成功读取 data/a.xls 目录下的 Excel 文件了,输出结果如下:
在这里插入图片描述

POI 的使用
POI 是用 Java 编写的免费开源的跨平台 Excel 处理 API,功能要比 Jxl 强大得多。其提供了对 Excel、Word、PowerPoint、Visio 等格式文档的读写操作。

API 文档对应的地址为:http://poi.apache.org/apidocs/index.html

在使用 POI 之前,需要基于 Maven 工程的 pom.xml 文件配置所需的 Jar 包:

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.17</version>
</dependency>

在 POI 中,操作 .xls(2007版以前的 Excel)文件,经常使用以下几个操作类:
在这里插入图片描述
在这里插入图片描述
了解了以上操作类,下面我将讲解如何使用 POI 工具进行 Excel 数据的读写,其涉及到 .xls 以及 .xlsx 两种数据格式。

POI 数据写入
针对 .xls 格式数据,我们使用的是 HSSF 开头的操作类。写入数据步骤大体如下。

  1. 创建输出流,即需要确定写入的文件目录:
//创建文件输出流
File file = new File("data/b.xls");
OutputStream outputStream = new FileOutputStream(file);
  1. 使用 POI 创建 Excel 工作簿及工作表:
//创建工作簿及工作表
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Sheet1");
  1. 使用 HSSFSheet 类中的方法 createRow() 创建某行,使用 HSSFRow 类中的方法 createCell() 创建某列,使用 HSSFCell 类中的方法 setCellValue() 为该单元格赋值,具体操作代码如下:
//添加表头
HSSFRow row = sheet.createRow(0); //常见某行
row.createCell(0).setCellValue("post_id");
row.createCell(1).setCellValue("post_title");
//添加内容
for(int i = 0; i < 2; i++){
    HSSFRow everyRow = sheet.createRow(i + 1);
    everyRow.createCell(0).setCellValue("帖子id为:0" + i);
    everyRow.createCell(1).setCellValue("帖子内容为:" + i);
}
  1. 数据写入工作目录,并释放资源:
workbook.write(outputStream);
workbook.close();
outputStream.close();

基于上述四个步骤的操作,便可成功将数据写入 .xls 文件中:
在这里插入图片描述
对 .xlsx 格式数据的操作流程与 .xls 相同,只不过要将操作 .xls 的类换成操作 .xlsx 的类,我这里直接给出了操作代码:

//创建文件输出流
File file = new File("data/b.xlsx");
OutputStream outputStream = new FileOutputStream(file);
//创建工作簿及工作表
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Sheet1");
//添加表头
XSSFRow row = sheet.createRow(0); //常见某行
row.createCell(0).setCellValue("post_id");
row.createCell(1).setCellValue("post_title");
//添加内容
for(int i = 0; i < 2; i++){
    XSSFRow everyRow = sheet.createRow(i + 1);
    everyRow.createCell(0).setCellValue("帖子id为:0" + i);
    everyRow.createCell(1).setCellValue("帖子内容为:" + i);
}
//数据写入工作目录,并释放资源
workbook.write(outputStream);
outputStream.close();

另外,操作 .xls 以及 .xlsx 的接口是相同的,这里我给了一个判断文件是 .xls 还是 .xlsx 文件的操作方法。基于此方法,既可以处理 .xls 文件也可以处理 .xlsx 文件,具体操作程序如下:

public class PoiExcelProcess {
    public static void main(String[] args) throws IOException {
        //文件名称
        File file = new File("data/c.xls");
        //File file = new File("data/c.xlsx");
        OutputStream outputStream = new FileOutputStream(file);
        Workbook workbook = getWorkBook(file);
        Sheet sheet = workbook.createSheet("Sheet1");
        //添加表头
        Row row = sheet.createRow(0); //常见某行
        row.createCell(0).setCellValue("post_id");
        row.createCell(1).setCellValue("post_title");
        //添加内容
        for(int i = 0; i < 2; i++){
            Row everyRow = sheet.createRow(i + 1);
            everyRow.createCell(0).setCellValue("帖子id为:0" + i);
            everyRow.createCell(1).setCellValue("帖子内容为:" + i);
        }
        workbook.write(outputStream);
        //释放资源
        workbook.close();
        outputStream.close();
    }
    //判断Excel的版本,初始化不同的Workbook
    public static Workbook getWorkBook(File file) throws IOException{
        Workbook workbook = null;
        //Excel 2003
        if(file.getName().endsWith("xls")){     
            workbook = new HSSFWorkbook();
        // Excel 2007以上版本
        }else if(file.getName().endsWith("xlsx")){    
            workbook = new XSSFWorkbook();
        }
        return workbook;
    }
}

POI 数据读取
POI 对 .xls 以及 .xlsx 数据的读取与数据的写入类似,可以单独使用各自的操作类进行读取,也可以先判断数据是 .xls 格式还是 .xlsx 格式,然后再进行读取。以下,给出了判断文件格式的方法:

 public static Workbook getWorkBook(File file) throws IOException{
        //输入流
        InputStream in = new FileInputStream(file);
        Workbook workbook = null;
        //Excel 2003
        if(file.getName().endsWith("xls")){     
            workbook = new HSSFWorkbook(in);
        // Excel 2007以上版本
        }else if(file.getName().endsWith("xlsx")){    
            workbook = new XSSFWorkbook(in);
        }
        in.close();
        return workbook;
    }

读取数据的具体流程如下。

  1. 确定要读取的 Excel 文件,并根据文件名称获取工作簿以及要操作的工作表,这里调用了上面的判断文件格式的方法 getWorkBook:
//文件名称
File file = new File("data/c.xls");
//File file = new File("data/c.xlsx");
Workbook workbook = getWorkBook(file);//根据文件名称获取操作工作簿
Sheet sheet = workbook.getSheet("Sheet1");//获取读取的工作表,这里有两种方式
//Sheet sheet=workbook.getSheetAt(0);
  1. 获取该表格的总行数,并按行读取数据,最后释放资源:
int allRow = sheet.getLastRowNum();//获取行数
//按行读取数据
for (int i = 0; i <= allRow; i++) {
    Row row = sheet.getRow(i);
    //获取列数
    short lastCellNum = row.getLastCellNum();
    for (int j = 0; j < lastCellNum; j++) {
        String cellValue = row.getCell(j).getStringCellValue();
        System.out.print(cellValue + "\t");
    }
    System.out.println();
}
//释放资源
workbook.close();

以下是上述程序在控制台输出的结果:
在这里插入图片描述
网络爬虫中 Excel 存储实例
本篇仍以网易汽车某论坛(http://baa.bitauto.com/CS55/)的帖子爬取为例,讲解在网络爬虫中如何将数据保存到 Excel 中。

爬取数据前,首先确定要爬的数据内容,例如我要爬的是该网页的帖子 id 以及帖子标题。根据自己所要爬的内容,创建 Bean 对象。具体程序如下:

public class PostModel {
    private String post_id; //帖子id
    private String post_title; //帖子标题
    public String getPost_id() {
        return post_id;
    }
    public void setPost_id(String post_id) {
        this.post_id = post_id;
    }
    public String getPost_title() {
        return post_title;
    }
    public void setPost_title(String post_title) {
        this.post_title = post_title;
    }
}

接着,确定需要使用的网页请求工具,这里使用较为简单的 jsoup 请求(通过如下 Maven 配置所需 Jar 包):

<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.3</version>
</dependency>
public class CrawlerTest {
    public static void main(String[] args) throws IOException, RowsExceededException, WriteException 
    {
        //获取数据
        List<PostModel> data = crawerData("http://baa.bitauto.com/CS55/");
        //存储数据
        DataToExcelByJxl.writeInfoListToExcel("data/post.xls","sheet1",data);
    }
    //解析数据
    static List<PostModel> crawerData(String url) throws IOException{
        //所爬数据封装于集合中
        List<PostModel> datalist = new ArrayList<PostModel>();
        //获取URL对应的HTML内容
        Document doc = Jsoup.connect(url).timeout(5000).get();
        //定位需要采集的每个帖子
        Elements elements = doc.select("div[class=line-bg]").select("div[class=postslist_xh]"); 
        //遍历每一个帖子
        for (Element ele : elements) {
            String post_id = ele.select("li.bt").select("a").attr("href").split("-")[1].replaceAll("\\D", "");
            String post_title = ele.select("li.bt").select("a").text();
            //创建对象和封装数据
            PostModel model = new PostModel();
            model.setPost_id(post_id);
            model.setPost_title(post_title);
            datalist.add(model);
        }
        return datalist;
    }
}

上述代码中,包括了请求 URL,解析 URL 对应的 HTML 内容,以及使用 List 集合封装数据,最后将封装的数据存储到 post.xls 表格中(调用了 DataToExcel 类中的 writeInfoListToExcel 方法)。而 writeInfoListToExcel 的输入为需要保存的文件目录地址,需要写入的工作表以及 PostModel 对象封装的集合。该类具体内容为:

public class DataToExcelByJxl {
    public static void writeInfoListToExcel(String filePath,String sheetName,List<PostModel> datalist) throws RowsExceededException, WriteException, IOException
    {
        File xlsFile = new File(filePath);
        WritableWorkbook workbook = Workbook.createWorkbook(xlsFile);//创建工作簿
        WritableSheet sheet = workbook.createSheet(sheetName, 0);// 创建一个工作表
        sheet.addCell(new Label(0, 0, "post_id"));//添加表头
        sheet.addCell(new Label(1, 0, "post_title"));//添加表头
        //添加内容
        for(int i=0;i<datalist.size();i++){
            sheet.addCell(new Label(0,i+1,datalist.get(i).getPost_id()));
            sheet.addCell(new Label(1,i+1,datalist.get(i).getPost_title()));
        }
        workbook.write();
        workbook.close();
        System.out.println(">>>>>>>>>数据写入完成!<<<<<<<<<<<<<");
    }
}

运行主方法,便可成功将该网站中对应的帖子信息成功保存到 Excel 中。
在这里插入图片描述
代码:https://github.com/soberqian/ExcelProcessInCrawler

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值