当前位置: 首页 > news >正文

java无极树形结构_Java爬虫框架:SeimiCrawler——结构化解析与数据存储

本文将介绍如何使用SeimiCrawler将页面中信息提取为结构化数据并存储到数据库中,这也是大家非常常见的使用场景。数据抓取将以抓取博客园的博客为例。

建立基本数据结构

为了演示,简单起见只建立一个用来存储博客标题和内容两个主要信息的表即可。表如下:

CREATE TABLE `blog` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`title` varchar(300) DEFAULT NULL,

`content` text,

`update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

同时建一个与之对应的Bean对象,如下:

package cn.wanghaomiao.model;

import cn.wanghaomiao.seimi.annotation.Xpath;

import org.apache.commons.lang3.StringUtils;

import org.apache.commons.lang3.builder.ToStringBuilder;

/**

* Xpath语法可以参考 http://jsoupxpath.wanghaomiao.cn/

*/

public class BlogContent {

@Xpath("//h1[@class='postTitle']/a/text()|//a[@id='cb_post_title_url']/text()")

private String title;

//也可以这么写 @Xpath("//div[@id='cnblogs_post_body']//text()")

@Xpath("//div[@id='cnblogs_post_body']/allText()")

private String content;

public String getTitle() {

return title;

}

public void setTitle(String title) {

this.title = title;

}

public String getContent() {

return content;

}

public void setContent(String content) {

this.content = content;

}

@Override

public String toString() {

if (StringUtils.isNotBlank(content)&&content.length()>100){

//方便查看截断下

this.content = StringUtils.substring(content,0,100)+"...";

}

return ToStringBuilder.reflectionToString(this);

}

}

这里面的@Xpath注解要着重介绍下,注解中配置的是针对对应字段的XPath提取规则,后面会介绍到SeimiCrawler会调用Response.render(Class bean)来自动解析填充对应字段。对于开发者而言,提取结构化数据所要做的最主要的工作就在这里,且就这么多,接下来介绍的就是整体上如何串起来的。

实现数据存储

本文演示使用的是paoding-jade,一款人人网早期开源出来的ORM框架。由于SeimiCrawler的对象池以及依赖管理是使用spring来实现的,所以SeimiCrawler天然支持一切可以和spring整合的ORM框架。 要启用Jade需添加pom依赖:

net.paoding

paoding-rose-jade

2.0.u01

org.apache.commons

commons-dbcp2

2.1.1

mysql

mysql-connector-java

5.1.37

添加resources下seimi-jade.xml配置文件:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

编写DAO,

package cn.wanghaomiao.dao;

import cn.wanghaomiao.model.BlogContent;

import net.paoding.rose.jade.annotation.DAO;

import net.paoding.rose.jade.annotation.ReturnGeneratedKeys;

import net.paoding.rose.jade.annotation.SQL;

@DAO

public interface StoreToDbDAO {

@ReturnGeneratedKeys

@SQL("insert into blog (title,content,update_time) values (:1.title,:1.content,now())")

public int save(BlogContent blog);

}

数据存储搞定后接下来就是我们的爬虫规则类了

Crawler

直接上:

package cn.wanghaomiao.crawlers;

import cn.wanghaomiao.dao.StoreToDbDAO;

import cn.wanghaomiao.model.BlogContent;

import cn.wanghaomiao.seimi.annotation.Crawler;

import cn.wanghaomiao.seimi.struct.Request;

import cn.wanghaomiao.seimi.struct.Response;

import cn.wanghaomiao.seimi.def.BaseSeimiCrawler;

import cn.wanghaomiao.xpath.model.JXDocument;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**

* 将解析出来的数据直接存储到数据库中

*/

@Crawler(name = "storedb")

public class DatabaseStoreDemo extends BaseSeimiCrawler {

@Autowired

private StoreToDbDAO storeToDbDAO;

@Override

public String[] startUrls() {

return new String[]{"http://www.cnblogs.com/"};

}

@Override

public void start(Response response) {

JXDocument doc = response.document();

try {

List urls = doc.sel("//a[@class='titlelnk']/@href");

logger.info("{}", urls.size());

for (Object s:urls){

push(Request.build(s.toString(),"renderBean"));

}

} catch (Exception e) {

//ignore

}

}

public void renderBean(Response response){

try {

BlogContent blog = response.render(BlogContent.class);

logger.info("bean resolve res={},url={}",blog,response.getUrl());

//使用神器paoding-jade存储到DB

int blogId = storeToDbDAO.save(blog);

logger.info("store sus,blogId = {}",blogId);

} catch (Exception e) {

//ignore

}

}

}

Github上亦有完整的demo,大家可以下载下来,自行尝试,点击直达。

相关文章:

  • mysql 单实例部署_Mysql5.7源码单实例部署
  • java map的常用方法_Java Map的三种常用遍历方法
  • java企业邮箱发送_java使用网易163企业个性域名邮箱发送邮件教程
  • java自定义函数的格式_PG自定义函数写法说明
  • java中取消异常提醒_我们如何确定应在Java中检查或取消选中自定义异常?
  • mysql技术大会2020_2020年数据库技术大会助力技术提升
  • java byte 解压_java-如何使用Zstd-jni和字节缓冲区解压缩大...
  • 查看Java项目中各类加载顺序_Web.xml在JAVA项目中的加载顺序是什么
  • vs2017nuget安装java包_VSCode使用dotnet命令安装Nuget包及配置Nuget源的方法
  • java dispatcher详解_SpringBoot之DispatcherServlet详解及源码解析
  • php注册程序,简单的php 用户注册程序[全套]
  • php unset 变量,php unset全局变量运用问题的深入解析
  • php chroot,PHP-FPM的chroot和chdir目录
  • php图片上传怎么跨域,php后端控制可跨域的域名并且允许图片跨域上传的方法介绍...
  • java 并发 关键字,java – 关于并发的最终关键字保证究竟是什么?