Java动态代理实现动态爬虫

Java动态代理实现动态爬虫笔者公司是一家区块链门户网站,该网站的很多资讯,快讯,视频等数据都是通过爬虫爬取得第三方网站获得的,需要从很多网站要爬取数据,如果每个数据源网站都需要单独写个接口去爬的话,工作量无疑是巨大的,因为笔者想到了通过动态代理实现一套爬虫机制,每次要爬取新的数据源,只要在数据库里增加一条数据源即可,无需修改代码。废话不多说,下贴出数据库表结构DROPTABLEIFEXISTS…

大家好,又见面了,我是你们的朋友全栈君。

笔者公司是一家区块链门户网站,该网站的很多资讯,快讯,视频等数据都是通过爬虫爬取得第三方网站获得的,需要从很多网站要爬取数据,如果每个数据源网站都需要单独写个接口去爬的话,工作量无疑是巨大的,因为笔者想到了通过动态代理实现一套爬虫机制,每次要爬取新的数据源,只要在数据库里增加一条数据源即可,无需修改代码。
废话不多说,下贴出数据库表结构

DROP TABLE IF EXISTS `yiyi_crawler_website`;
CREATE TABLE `yiyi_crawler_website` ( `id` bigint(16) NOT NULL AUTO_INCREMENT COMMENT '自增ID', `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', `url` varchar(255) DEFAULT NULL COMMENT '网站链接(抓取内容的接口)', `interval` bigint(16) DEFAULT '0' COMMENT '抓取时间间隔(以毫秒为单位)', `website_type` tinyint(20) DEFAULT NULL COMMENT '网站类型(1、快讯)', `website_name` varchar(32) DEFAULT NULL COMMENT '网站名', `source_link` varchar(255) DEFAULT NULL COMMENT '来源链接', `data_field` varchar(32) DEFAULT NULL COMMENT '数据所在字段,如果没有,为空则直接取数(多级以.连接,如果:data.items表示data下面的items为内容列表)', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `yiyi_crawler_website_content`;
CREATE TABLE `yiyi_crawler_website_content` ( `id` bigint(16) NOT NULL AUTO_INCREMENT, `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', `website_id` bigint(16) DEFAULT NULL COMMENT '网站ID', `content_name` varchar(16) DEFAULT NULL COMMENT '内容名', `table_name` varchar(32) DEFAULT NULL COMMENT '所属表名', `column_name` varchar(32) DEFAULT NULL COMMENT '所属字段名', `return_field` varchar(32) DEFAULT NULL COMMENT '当前要抓取的字段所返回的字段', `field_type` tinyint(2) DEFAULT '2' COMMENT '字段类型(1、日期2、数值0、其他)', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

下面贴出爬虫的动态代理实现,基于cglib框架实现的

/** * 爬虫任务代理接口 * * @author liyi * @create 2018-03-17 16:58 **/
public interface CrawlerProxy { 

/** * 任务开始 * @param website */
void start(CrawlerWebsiteModelOut website);
}
/** * 爬虫任务类 * * @author liyi * @create 2018-03-17 18:21 **/
public class CrawlerTask implements CrawlerProxy { 

@Override
public void start(CrawlerWebsiteModelOut website) {
System.out.println("爬虫任务开始");
}
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lynn.yiyi.http.Request;
import com.lynn.yiyi.http.WebUtils;
import com.lynn.yiyi.model.out.CrawlerWebsiteModelOut;
import java.util.*;
/** * 爬虫定时任务 * * @author liyi * @create 2018-03-17 18:35 **/
public class CrawlerTimerTask extends TimerTask { 

private CrawlerWebsiteModelOut website = null;
@Override
public void run() {
String json = WebUtils.executeHttp(Request.options().setMethod(com.lynn.yiyi.http.Method.GET).setUrl(website.getUrl()).build()).getJsonString();
String strs[] = website.getDataField().split(".");
List<String> dataList = new ArrayList<>();
Arrays.stream(strs).forEach(s -> {
dataList.clear();
String data = JSON.parseObject(json, new TypeReference<Map<String, List<Map<String, String>>>>() {}.getType());
dataList.add(data);
});
}
public void setWebsite(CrawlerWebsiteModelOut website) {
this.website = website;
}
public CrawlerWebsiteModelOut getWebsite() {
return website;
}
}
import com.alibaba.fastjson.JSONObject;
import com.lynn.yiyi.http.Request;
import com.lynn.yiyi.http.WebUtils;
import com.lynn.yiyi.model.out.CrawlerWebsiteModelOut;
import com.lynn.yiyi.service.CrawlerService;
import com.lynn.yiyi.utils.SpringUtils;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/** * 爬虫动态代理类 * * @author liyi * @create 2018-03-17 18:22 **/
public class CrawlerCglibProxy implements MethodInterceptor { 

private Map<Long,Timer> timerMap = new HashMap<>();
private Enhancer enhancer = new Enhancer();
Object getProxy(Class<?> clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object o = proxy.invokeSuper(obj,args);
if("start".equals(method.getName())){
if(args[0] instanceof CrawlerWebsiteModelOut){
CrawlerWebsiteModelOut website = (CrawlerWebsiteModelOut)args[0];
if(timerMap.get(website.getId()) == null){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
String data = WebUtils.executeHttp(Request.options().setMethod(com.lynn.yiyi.http.Method.GET).setUrl(website.getUrl()).build()).getJsonString();
String strs[] = website.getDataField().split("\\.");
for (String s : strs) {
JSONObject object = JSONObject.parseObject(data);
data = object.getString(s);
}
//TODO 这里将爬取到的数据写到数据库对应的表中
}
}, 0, website.getInterval());
timerMap.put(website.getId(),timer);
}
}
}
return o;
}
public static <T> T create(Class<T> cls){
CrawlerCglibProxy proxy = new CrawlerCglibProxy();
return (T)proxy.getProxy(cls);
}
}
import java.util.ArrayList;
import java.util.List;
/** * 网站爬虫输出参数 * * @author liyi * @create 2018-03-17 17:04 **/
public class CrawlerWebsiteModelOut extends BaseModelOut { 

private String url;
private Long interval;
private Integer websiteType;
private String websiteName;
private String sourceLink;
private String dataField;
private List<CrawlerWebsiteContentModelOut> contentList = new ArrayList<>();
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Long getInterval() {
return interval;
}
public void setInterval(Long interval) {
this.interval = interval;
}
public Integer getWebsiteType() {
return websiteType;
}
public void setWebsiteType(Integer websiteType) {
this.websiteType = websiteType;
}
public String getWebsiteName() {
return websiteName;
}
public void setWebsiteName(String websiteName) {
this.websiteName = websiteName;
}
public String getSourceLink() {
return sourceLink;
}
public void setSourceLink(String sourceLink) {
this.sourceLink = sourceLink;
}
public String getDataField() {
return dataField;
}
public void setDataField(String dataField) {
this.dataField = dataField;
}
public List<CrawlerWebsiteContentModelOut> getContentList() {
return contentList;
}
public void setContentList(List<CrawlerWebsiteContentModelOut> contentList) {
this.contentList = contentList;
}
}
/** * 爬虫网站内容输出参数 */
public class CrawlerWebsiteContentModelOut extends BaseModelOut{ 

private Long websiteId;
private String contentName;
private String tableName;
private String columnName;
private String returnField;
private Integer fieldType;
public Long getWebsiteId() {
return websiteId;
}
public void setWebsiteId(Long websiteId) {
this.websiteId = websiteId;
}
public String getContentName() {
return contentName;
}
public void setContentName(String contentName) {
this.contentName = contentName;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getReturnField() {
return returnField;
}
public void setReturnField(String returnField) {
this.returnField = returnField;
}
public Integer getFieldType() {
return fieldType;
}
public void setFieldType(Integer fieldType) {
this.fieldType = fieldType;
}
}
import java.util.Date;
/** * 基础输出参数 * * @author liyi * @create 2018-03-17 17:02 **/
public abstract class BaseModelOut{ 

private Long id;
private Date create;
private Date modified;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getCreate() {
return create;
}
public void setCreate(Date create) {
this.create = create;
}
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
}

下面给出测试的main方法

public static void main(String[] args) {
CrawlerProxy proxy = CrawlerFactory.create();
proxy.start(website);//website即当前要爬取的网站对象,可以从数据库中读取
}

调用了main方法即可启动定时器,定时从指定website爬取数据。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159775.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 字符串常量池有什么用_字符串常量池在堆中还是方法区

    字符串常量池有什么用_字符串常量池在堆中还是方法区看网上的介绍,对于字符串常量池中到底保存的是字符串对象,还是字符串对象的引用,众说纷纭…看jdk1.8对intern()的说明.Whentheinternmethodisinvoked,ifthepoolalreadycontainsastringequaltothisStringobjectasdeterminedbytheequals(…

  • 使用FastJson对JSON字符串、JSON对象及JavaBean之间的相互转换

    使用FastJson对JSON字符串、JSON对象及JavaBean之间的相互转换maven依赖包:<!–https://mvnrepository.com/artifact/com.alibaba/fastjson–><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId>…

    2022年10月18日
  • 8 款免费的 MySQL 数据库建模工具

    数据库建模和设计是软件开发过程中必不可少的步骤,一个良好的建模工具可以帮助我们简单快速地完成数据库设计,提高工作的效率。因此,今天给大家推荐几款免费的MySQL数据库建模工具,包括MySQLWorkbench、SQLPowerArchitect、PDMan、RISE、GenMyModel、DBDesigner、dbdiagram.io、Freedgo。

  • Windows 技术篇-LDSGameMaster文件夹有什么用,删除方法

    Windows 技术篇-LDSGameMaster文件夹有什么用,删除方法LDS是鲁大师的拼写,应该是用过鲁大师,偷偷给你安装的。分析:没什么用,流氓程序,还很大占地方,4个G,可以放心的卸掉。卸载方法:找到里面的卸载程序来卸载,卸载完后把文件夹删除就好了。

  • Solr使用入门指南

    Solr使用入门指南

  • 酒店管理系统源码_客户管理系统源码

    酒店管理系统源码_客户管理系统源码(1)资源完全开放型:系统所有的资源,功能交由用户管理,权限控制到按钮,针对不同的用户,组装不同的界面,分配不同的使用功能.不放心再加权限到按钮。(2)系统突出以营销、预订、房源、房价等对营销具有影响力的信息处理。房价码可按年,季,月,周,日设定。(3)强化以客源为中心的信息完整性、长久性、可操作性。建立了客档为中心的用户信息管理系统。(4)使用数据穿透查询技术,对数据进行多元,多层次的查询.从汇中数据到明细发生,紧密联系在一起,灵活实用。(5)客档、角色、佣金、房价方案、授权折扣、操作权

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号