JobProcessor类,用于抓取并解析网页内容获取需要的数据
@Component public class JobProcessor implements PageProcessor { private Logger logger = LoggerFactory.getLogger(this.getClass()); /** 自定以的数据处理类,该类继承了Pipeline接口,并实现了其process方法 */ @Autowired private SpringDataPipeline springDataPipeline; /** 需要抓取的url列表页 */ private String url = "https://search.51job.com/list/000000,000000,0000,32%252C01,9,99," + "Java,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99" + "&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0" + "&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare="; /** 设置请求的页面解析的编码,请求的超时时间,每台服务的请求时间与重试次数 */ private Site site = Site.me() .setCharset("gbk") .setTimeOut(10000) .setRetrySleepTime(3000) .setRetryTimes(3); @Override public void process(Page page) { //解析页面,获取招聘信息详情页的url地址 List<Selectable> nodes = page.getHtml().css("div#resultList div.el").nodes(); //判断获取到的集合是否weikong,如果为空表示这个招聘详情页,如果不为空则表示这是列表页 if (nodes == null || nodes.size() == 0) { // 如果为空,则表示这是招聘详情页,解析页面获取招聘详情信息保存数据 this.saveJobInfo(page); } else { // 如果不为空,则表示这是列表页解析出详情页的URL地址,放到任务队列中 for (Selectable selectable : nodes) { // 获取URL地址 String jobInfoUrl = selectable.links().toString(); // 将获取到的URL地址放到任务队列中 page.addTargetRequest(jobInfoUrl); } // 获取下一页的url String nextPageUrl = page.getHtml().css("div.p_in li.bk").nodes().get(1).links().toString(); // 把url放到任务队列中 page.addTargetRequest(nextPageUrl); } } /** * 功能描述:saveJobInfo,解析页面获取招聘详情信息,保存数据 <br> * @param page * @return void * * @Author xu * @Date 2020-03-15 21:38 * @Version 1.0.0 */ private void saveJobInfo(Page page) { // 创建招聘详情对象 JobInfo jobInfo = new JobInfo(); // 解析页面 Html html = page.getHtml(); // 获取数据封装到对象中 jobInfo.setCompanyName(html.css("div.cn p.cname a", "text").toString()); String companyAddr = Jsoup.parse(html.css("div.bmsg").nodes().get(1).toString()).text(); jobInfo.setCompanyAddr(companyAddr.substring(0, companyAddr.length()-3)); jobInfo.setCompanyInfo(Jsoup.parse(html.css("div.tmsg").toString()).text()); jobInfo.setJobName(html.css("div.cn h1", "text").toString()); String[] jobAndTime = html.css("div.cn p.ltype", "text").toString().split(" "); jobInfo.setJobAddr(jobAndTime[0]); jobInfo.setJobInfo(Jsoup.parse(html.css("div.job_msg").toString()).text()); jobInfo.setUrl(page.getUrl().toString()); String text = html.css("div.cn strong", "text").toString(); Integer[] salary = SalatyUtils.getSalary(text); jobInfo.setSalaryMin(salary[0]); jobInfo.setSalaryMax(salary[1]); String time = null; for (int i=0; i< jobAndTime.length; i++) { String s = jobAndTime[i]; if (s.contains("发布")) { time = s.substring(0, s.length()-2); } } jobInfo.setTime(time); // 保存结果 page.putField("jobInfo", jobInfo); } @Override public Site getSite() { return site; } /** * 功能描述:initialDelay任务启动后等待多久执行,fixedDelay任务执行的间隔时间 <br> * @param * @return void * * @Author xu * @Date 2020-03-15 21:21 * @Version 1.0.0 */ @Scheduled(initialDelay = 1000, fixedDelay = 100000) public void doProcess() { logger.info("============ 任务开始执行 ============"); Spider.create(new JobProcessor()) .addUrl(url) .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000))) .thread(10) .addPipeline(this.springDataPipeline) .run(); logger.info("============ 任务执行完成 ============"); } }SpringDataPipeline类,用于数据处理后放入数据库中
@Component public class SpringDataPipeline implements Pipeline { @Autowired private JobInfoService jobInfoService; @Override public void process(ResultItems resultItems, Task task) { // 获取封装好的招聘信息对象 JobInfo jobInfo = resultItems.get("jobInfo"); // 判断数据是否为空,如果不为空则将数据保存到数据库中 if (jobInfo != null) { this.jobInfoService.save(jobInfo); } } }SalatyUtils类,JobProcessor中调用的方法用于处理网页中的数据
public class SalatyUtils { public static Integer[] getSalary(String salaryString) { Integer[] salaryArr = new Integer[2]; String itemSalaty = salaryString.substring(0, salaryString.length()-3); String itemMath = salaryString.substring(salaryString.length()-3, salaryString.length()); String[] salary = itemSalaty.split("-"); if (itemMath.contains("千")) { salaryArr[0] = new BigDecimal(salary[0]).multiply(new BigDecimal(1000)).intValue(); salaryArr[1] = new BigDecimal(salary[1]).multiply(new BigDecimal(1000)).intValue(); } else { if (itemMath.contains("月")) { salaryArr[0] = new BigDecimal(salary[0]).multiply(new BigDecimal(10000)).intValue(); salaryArr[1] = new BigDecimal(salary[1]).multiply(new BigDecimal(10000)).intValue(); } else { salaryArr[0] = new BigDecimal(salary[0]).multiply(new BigDecimal(10000/12)).intValue(); salaryArr[1] = new BigDecimal(salary[1]).multiply(new BigDecimal(10000/12)).intValue(); } } return salaryArr; } }以上为个人总结的一些笔记,若有雷同纯属巧合,若有错误欢迎指出,谢谢!