# crawler **Repository Path**: sedricd/crawler ## Basic Information - **Project Name**: crawler - **Description**: 通用爬虫骨架 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2022-02-25 - **Last Updated**: 2022-02-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # crawler #### 介绍 通用爬虫骨架,一个简单,高效,易扩展的爬虫框架,适用于各种场景。 #### 软件架构 > 整个爬虫项目的基本骨架如下图所示: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0807/172855_c413289a_5011140.png "屏幕截图.png") 简单说明一下本框架的基本工作原理: 1.**CrawlerEngine** 这个类是爬虫引擎的抽象类,定义了爬虫引擎的加载,启动,暂停,重启,停止等操作。 **Crawler** 是一个核心爬虫工作单元,定义了爬虫的地址,爬虫的类型,爬虫任务列表等一些信息。 **Task** 是爬虫任务执行单元。一个爬虫引擎可以部署多个爬虫单元,一个爬虫单元会有N多个爬虫任务执行。 2.爬虫执行任务单元分为 **SingleTask** (单页任务)和 **MultipleTask** (多页任务),由于数据量巨大,在设计系统的时候会采用分页展示的手段,分页分数就是为了针对这种情况而设计的。 3.当爬虫引擎部署好爬虫并且开始启动执行,那么首先会从爬虫单元(Crawler)中取出爬虫的目标地址等相关信息创建一个启动的Task,然后将Task放入TaskExecutor中执行,执行完成之后对执行结果进行解析-》处理解析结果-》清理数据缓存,到此处这个Task执行完毕,然后再从爬虫单元中取出下一个Task进行任务分发。具体的详细过程大家可以参考源代码自己研究。 #### 安装教程 1.克隆本项目到本地, git clone git@gitee.com:superamxing/crawler.git 2.使用maven安装到本地仓库中即可,mvn clean install #### 使用说明 1. 创建一个Springboot项目 2. 然后在pom中添加如下依赖 ``` com.simple crawler 1.2-SNAPSHOT ``` 3. 修改一下启动类,实现CrawlerInitialize接口 ``` @SpringBootApplication(scanBasePackages = {"com.simple"}) public class DemoApplication implements CrawlerInitialize { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(DemoApplication.class, args); } @Override public void doAfter() throws Exception { SchedulerManager schedulerManager = CrawlerContext.getObj(SchedulerManager.class); if (schedulerManager == null) { return; } schedulerManager.initialize(null); schedulerManager.addJob(TaskExecutor.class, SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()); } } ``` 启动之后有如下日志,则表明爬虫引擎已正式启动 ``` 2019-08-07 20:20:59.019 INFO 17368 --- [ main] com.simple.crawler.core.CrawlerContext : --------------------》初始化爬虫引擎开始《-------------------- 2019-08-07 20:20:59.089 INFO 17368 --- [ main] org.quartz.impl.StdSchedulerFactory : Using default implementation for ThreadExecutor 2019-08-07 20:20:59.090 INFO 17368 --- [ main] org.quartz.simpl.SimpleThreadPool : Job execution threads will use class loader of thread: main 2019-08-07 20:20:59.097 INFO 17368 --- [ main] org.quartz.core.SchedulerSignalerImpl : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2019-08-07 20:20:59.097 INFO 17368 --- [ main] org.quartz.core.QuartzScheduler : Quartz Scheduler v.2.3.1 created. 2019-08-07 20:20:59.098 INFO 17368 --- [ main] org.quartz.simpl.RAMJobStore : RAMJobStore initialized. 2019-08-07 20:20:59.098 INFO 17368 --- [ main] org.quartz.core.QuartzScheduler : Scheduler meta-data: Quartz Scheduler (v2.3.1) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads. Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered. 2019-08-07 20:20:59.098 INFO 17368 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties' 2019-08-07 20:20:59.098 INFO 17368 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler version: 2.3.1 2019-08-07 20:20:59.099 INFO 17368 --- [ main] org.quartz.core.QuartzScheduler : Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started. 2019-08-07 20:20:59.106 INFO 17368 --- [ main] com.simple.crawler.core.CrawlerContext : --------------------》初始化爬虫引擎完毕《-------------------- ``` 4.创建一个SimpleTask类,如下 ``` public class SimpleTask extends SingleTask { @Setter(expr = "@text{title}") private String title; public SimpleTask(String crawlerId, Integer index, String url) { super(crawlerId, index, url); } @Override public T buildRequest() { return (T) HttpRequest.HttpRequestBuilder.create().url(getUrl()).build(); } @Override public void recovery() throws Exception { logger.info("抓取到的页面title为:{}", title); } } ``` 这段代码的作用就是就是获取这个网页的的title属性内容,其中@Setter注解就是将解析的数据注入到属性值中,比如说我们要抓取【 https://www.json.cn/ 】页面的title内容,则用以下的代码来启动: ``` CrawlerContext.getObj(CrawlerEngine.class).deploy("https://www.json.cn/", SimpleTask.class).start(); ``` 执行结果如下 ``` 2019-08-07 20:30:04.647 INFO 12128 --- [eduler_Worker-2] com.simple.crawler.aop.Listener : [id=a890910f699d49e58]:爬虫ID【1a2505cb49ff494db353502edf365a5e】,任务处理类【com.simple.demo.task.SimpleTask$$EnhancerByCGLIB$$d497d5d0】,任务ID【e855a60b73354b61b9b4b03fe53c464b】,任务类型【单页任务】,处理url【https://www.json.cn/】 2019-08-07 20:30:05.435 INFO 12128 --- [eduler_Worker-2] com.simple.demo.task.SimpleTask : [id=61db44c4c7ff4167a]:抓取到的页面title为:JSON在线解析及格式化验证 - JSON.cn 2019-08-07 20:30:05.435 INFO 12128 --- [eduler_Worker-2] com.simple.crawler.aop.Listener : [id=a890910f699d49e58]:本次共耗时:791ms,响应值:null ``` #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 码云特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)