将爬取结果保存成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);
}
}
}