[Java爬虫-WebMagic]-06-将爬取结果保存成Excel

将爬取结果保存成Excel

我们可以吧爬取的结果保存成一个Excel文件,方便计算
也方便别人查看


导包

Gradle

//爬虫包
compile group: 'us.codecraft', name: 'webmagic-core', version: '0.7.3'
compile group: 'us.codecraft', name: 'webmagic-extension', version: '0.7.3'

//poi包 office操作
compile group: 'org.apache.poi', name: 'poi', version: '4.0.1'

Maven

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

<!-- 爬虫包 -->
<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-core</artifactId>
    <version>0.7.3</version>
</dependency>
<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-extension</artifactId>
    <version>0.7.3</version>
</dependency>

创建Pipeline

这里的代码信息量有点大,主要的部分我在源代码里备注了

class ExcelPipeline extends FilePersistentBase implements Pipeline{

    private String filename;//文件名
    private int rows = 0;//当前要编辑的行
    private HSSFWorkbook workbook;//工作蒲
    private HSSFSheet sheet;//工作表

    //这个是输出用的  如果不喜欢删掉这些一点影响也没有 把所有logger的东西都可以看做成 System.out.println()
    private Logger logger = LoggerFactory.getLogger(getClass());
    
	//构造方法
    public ExcelPipeline(String path) {

        //设置保存路径
        setPath(path);
		
		//设置文件名是日期格式
        filename = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +".xls";
        //创建工作薄对象
        workbook = new HSSFWorkbook();//这里也可以设置sheet的Name
        //创建工作表对象
        sheet = workbook.createSheet("爬取结果");

        //创建工作表的行
        HSSFRow row = sheet.createRow(rows);
        
        //创建标题
        row.createCell(0).setCellValue("id");
        row.createCell(1).setCellValue("名称");
        row.createCell(2).setCellValue("连接地址");
        
        //每写完一行我们就要开始写下一行
        rows++;
        
        

    }

    @Override
    public void process(ResultItems resultItems, Task task) {
        //提取保存的内容
        List<String> hrefs = resultItems.get("href");
        List<String> texts = resultItems.get("text");
		
		//输出 
        logger.debug(hrefs.toString());
        logger.debug(texts.toString());

        for (int i=0;i<hrefs.size();i++){
            //创建工作表的行
            HSSFRow row = sheet.createRow(rows);
            row.createCell(0).setCellValue(rows);
            row.createCell(2).setCellValue(hrefs.get(i));
            row.createCell(1).setCellValue(texts.get(i));
            rows++;
        }
        
		//写完之后保存
        save();
    }

    /** 保存表格 **/
    private synchronized void save() {
        try {
            //文档输出
            FileOutputStream out = new FileOutputStream(getFile(this.path+filename));
            workbook.write(out);
            out.close();
            logger.info(this.path+filename+"存储完毕");
        } catch (IOException e) {
            logger.warn("存储失败", e);
        }
    }



}

这里要说的是为什么要继承FilePersistentBase

他的源码如下

package us.codecraft.webmagic.utils;

import java.io.File;

/**
 * 文件持久性的基础对象。
 *	
 * @author [email protected] <br>
 * @since 0.2.0
 */
public class FilePersistentBase {

    protected String path;

    public static String PATH_SEPERATOR = "/";

    static {
        String property = System.getProperties().getProperty("file.separator");
        if (property != null) {
            PATH_SEPERATOR = property;
        }
    }

    public void setPath(String path) {
        if (!path.endsWith(PATH_SEPERATOR)) {
            path += PATH_SEPERATOR;
        }
        this.path = path;
    }

    public File getFile(String fullName) {
        checkAndMakeParentDirecotry(fullName);
        return new File(fullName);
    }

    public void checkAndMakeParentDirecotry(String fullName) {
        int index = fullName.lastIndexOf(PATH_SEPERATOR);
        if (index > 0) {
            String path = fullName.substring(0, index);
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
        }
    }

    public String getPath() {
        return path;
    }
}

这个基础对象会帮你省去一些文件方面的操作

例如:

  • 当写的文件夹不存在时候会帮你自动创建
  • 自动在path地址后面补充 "\"或者 “/”

配置爬虫入口

这里比较简单,不细说了

public static void main(String[] args) {
   //创建爬虫解析页面
    PageProcessor pageProcessor = new ExcelDemo();
    //创建爬虫
    Spider spider = Spider.create(pageProcessor);
    //给爬虫添加爬取地址
    spider.addUrl("https://blog.csdn.net/qq_18604209/rss/list");
    //启动一个线程
    spider.thread(1);
    //添加一个Pipeline
    spider.addPipeline(new ExcelPipeline("G:\\test"));
    //启动爬虫
    spider.run();
}

配置PageProcessor

匹配到结果之后吧结果的集合提取出来

@Override
public void process(Page page) {
    //抓取到的页面为一个page对象
    Html html = page.getHtml();//我们从page里面获取Html信息

    Selectable item =  html.$("item");//获取item标签

    Selectable title =  item.$("title","text");//获取items标签的 title 中的文字
    Selectable link =  item.$("guid","text");//获取items标签的 guid 中的文字

    title = title.replace("\\<!\\[CDATA\\[","");
    title = title.replace("\\]>","");

    page.putField("text",title.all());
    page.putField("href",link.all());

}

完成这些就可以运行程序了,然后你的文件夹里就会多出来一个xls文件,打开效果如下
在这里插入图片描述


完整的代码

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.codecraft.webmagic.*;
import us.codecraft.webmagic.pipeline.Pipeline;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.Selectable;
import us.codecraft.webmagic.utils.FilePersistentBase;

import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class ExcelDemo implements PageProcessor {

    @Override
    public void process(Page page) {
        //抓取到的页面为一个page对象
        Html html = page.getHtml();//我们从page里面获取Html信息

        Selectable item =  html.$("item");//获取item标签

        Selectable title =  item.$("title","text");//获取items标签的 title 中的文字
        Selectable link =  item.$("guid","text");//获取items标签的 guid 中的文字

        title = title.replace("\\<!\\[CDATA\\[","");
        title = title.replace("\\]>","");

        page.putField("text",title.all());
        page.putField("href",link.all());


    }

    @Override
    public Site getSite() {
        return Site.me();
    }


    public static void main(String[] args) {
        //创建爬虫解析页面
        PageProcessor pageProcessor = new ExcelDemo();
        //创建爬虫
        Spider spider = Spider.create(pageProcessor);
        //给爬虫添加爬取地址
        spider.addUrl("https://blog.csdn.net/qq_18604209/rss/list");
        //启动一个线程
        spider.thread(1);
        //添加一个Pipeline
        spider.addPipeline(new ExcelPipeline("G:\\test"));
        //启动爬虫
        spider.run();
    }

}

/** 自定义的Pipeline **/
class ExcelPipeline extends FilePersistentBase implements Pipeline{

    private String filename;//文件名
    private int rows = 0;//当前要编辑的行
    private HSSFWorkbook workbook;//工作蒲
    private HSSFSheet sheet;//工作表

    //这个是输出用的  如果不喜欢删掉这些一点影响也没有
    private Logger logger = LoggerFactory.getLogger(getClass());


    public ExcelPipeline(String path) {

        //设置保存路径
        setPath(path);

        filename = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +".xls";
        //创建工作薄对象
        workbook = new HSSFWorkbook();//这里也可以设置sheet的Name
        //创建工作表对象
        sheet = workbook.createSheet("爬取结果");

        //创建工作表的行
        HSSFRow row = sheet.createRow(rows);

        //创建标题
        row.createCell(0).setCellValue("id");
        row.createCell(1).setCellValue("名称");
        row.createCell(2).setCellValue("连接地址");

        //每写完一行我们就要开始写下一行
        rows++;
    }

    @Override
    public void process(ResultItems resultItems, Task task) {
        //提取保存的内容
        List<String> hrefs = resultItems.get("href");
        List<String> texts = resultItems.get("text");

        logger.debug(hrefs.toString());
        logger.debug(texts.toString());

        for (int i=0;i<hrefs.size();i++){
            //创建工作表的行
            HSSFRow row = sheet.createRow(rows);
            row.createCell(0).setCellValue(rows);
            row.createCell(2).setCellValue(hrefs.get(i));
            row.createCell(1).setCellValue(texts.get(i));
            rows++;
        }
        
		//写完之后保存
        save();
    }

    /** 保存表格 **/
    private synchronized void save() {
        try {
            //文档输出
            FileOutputStream out = new FileOutputStream(getFile(this.path+filename));
            workbook.write(out);
            out.close();
            logger.info(this.path+filename+"存储完毕");
        } catch (IOException e) {
            logger.warn("存储失败", e);
        }
    }

}


上一篇[Java爬虫-WebMagic]-05-多级爬取

发布了48 篇原创文章 · 获赞 44 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_18604209/article/details/104224341