一个java自动化爬虫场景,参考文档、代码注释非常详细!
爬虫文档说明
目标
java爬虫研招网 https://yz.chsi.com.cn/zsml/zyfx_search.jsp
码云地址
https://gitee.com/aluruihua/auto-move
需求
- 打开链接,有一个post提交的框显示所在省市、招生单位、门类类别、学科类别、专业名称、学习方式六项。
- 点击查询
- 每个查询页面的招生单位一栏都是学校的名字,点击进入学校对应的专业。
- 进入后的table中有一个查看超链接,点击进入。
- 里面有这个学校对应这个专业的信息。
本次需求是爬到所有可以post提交的的最里面的页面的所有有关学校的专业的所有信息。关键字段是拟招人数和考试范围。我也是帮我一个同学爬出这些数据,放到web页面展示,由于他想看比如北京计算机专业的拟招人数和考试范围,他需要一个一个点进去看一下。这样非常浪费时间,非常麻烦。哈哈爬出来展示可能好点。主要是想练习一下简单线程池的使用。本次是一个单节点,多线程的数据爬取。不存在封ip的情况。
开发环境及框架说明
- idea.
- jdk 1.8.
- spring boot 2.1.6.RELEASE.
- hutool 4.5.10 (java兵器库)
- quartz 2.2.3 (定时器)
- nutz.dao 1.r.60 (数据库层操作框架)
- jsoup 1.11.3(页面解析工具类)
- newFixedThreadPool(线程池)
CyclicBarrier (栅栏)
使用
- 将项目down下来。
- 在auto-move/src/resources/sql下有两个.sql文件,task是任务库,扫描任务库中状态为0的,插入bi库中,将两个sql文件导入本地mysql数据库中。
任务库中的任务已经添加一些,可以直接启动,查看bi库中数据的插入。
代码说明
- KaoyanThread.java
public void begin() {
List<Task> tasks = dao.query(Task.class, Cnd.where("status", "=", 0));//使用nutz扫描任务库中状态为0的任务
if (tasks.size()==0){
logger.info("*********所有任务执行完毕*****************");
} else {
//创建线程池
ExecutorService pool = Executors.newFixedThreadPool(size);
CyclicBarrier cyclicBarrier = new CyclicBarrier(size);//开启栅栏
for (int i=0;i<size;i++){
Task task = null;
KaoyanSonThread kaoyanSonThread = null;
try {
//创建几个线程池,就将每个任务添加到线程池中
task = tasks.get(i);//当报null指针的时候,就是任务快完的时候,所以使用try..catch...
}catch (Exception e){
logger.info("线程任务即将结束。。。。。。");
}
try {
kaoyanSonThread= new KaoyanSonThread(cyclicBarrier,dao,task);//这个类是线程类不受spring管理,通过构造注入,实现runable接口,具体看项目中代码。
pool.execute(kaoyanSonThread);
}catch (Exception e){
logger.error("线程池错误。。。。。");
}
}
//结束线程池
pool.shutdown();
}
}
- CronScheduler.java
@Component
@PropertySource(value = "classpath:run.properties",encoding = "UTF-8")
public class CronScheduler implements ApplicationRunner {
@Autowired
private Scheduler scheduler;
@Value("${task-cron}")
String cron;//通过配置文件获取自定义定时时间
@Override
public void run(ApplicationArguments args) throws Exception {
//jobDetail
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("cronJob").build();//定时器执行的方法HelloJob.class
//cronTrigger
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("cronTrigger").withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
scheduler.scheduleJob(jobDetail,cronTrigger);
scheduler.start();//启动定时任务
}
}
- 更改线程数和时间
打开run.properties文件,修改时间和线程数。本次配置为十秒钟,读3个线程。
不足之处,或者需要优化的地方可以联系我,觉得有用的给个star,谢谢。
相关文章