# 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
#### 介绍
通用爬虫骨架,一个简单,高效,易扩展的爬虫框架,适用于各种场景。
#### 软件架构
> 整个爬虫项目的基本骨架如下图所示:

简单说明一下本框架的基本工作原理:
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/)