package com.goafanti.crawler.callback; import java.util.ArrayList; import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.alibaba.fastjson.JSON; public class VacationFutureCallback extends CrawlerFutureCallback { private String year = null; private Pattern dateTime = null; private Pattern dateTimePeriod = null; private Pattern dateTimePeriod2 = null; private Set vacations = null; private Set workDays = null; public VacationFutureCallback(Map result) { setResult(result); } @Override protected void handleWebpage(String pageContent) { Pattern pattern = Pattern.compile("([\\s\\S]*?)", Pattern.MULTILINE); Matcher m = pattern.matcher(pageContent); if (m.find()) { handleNotice(m.group(1)); } } private void handleNotice(String notice) { Matcher yearMatcher = Pattern.compile("关于(\\d+)年").matcher(notice); if (yearMatcher.find()) { year = yearMatcher.group(1); } else { return; } List parts = new ArrayList<>(); Matcher linesMatcher = Pattern.compile("([\\s\\S]+?)

", Pattern.MULTILINE).matcher(notice); while (linesMatcher.find()) { parts.add(linesMatcher.group(1)); } handleParts(parts); } private void handleParts(List parts) { dateTime = Pattern.compile("(\\d+)月(\\d+)日"); dateTimePeriod = Pattern.compile("(\\d+)月(\\d+)日至(\\d+)日"); dateTimePeriod2 = Pattern.compile("(\\d+)月(\\d+)日至(\\d+)月(\\d+)日"); vacations = new HashSet<>(); workDays = new HashSet<>(); for (String part : parts) { for (String s : part.split("<.*?>")) { if (s.matches("\\d+月\\d+日.*")) { handleLine(s); } } } Calendar c = Calendar.getInstance(); int y = Integer.parseInt(year); c.set(y, 0, 1); while (c.get(Calendar.YEAR) == y) { int dow = c.get(Calendar.DAY_OF_WEEK); if (dow == 7 || dow == 1) { String ckey = getDateStr(c); if (!workDays.contains(ckey)) { vacations.add(ckey); } } c.add(Calendar.DATE, 1); } if (this.getResult() != null) { this.getResult().put(year, JSON.toJSONString(vacations)); } } private void handleLine(String line) { for (String s : line.split("。")) { boolean isVacation = s.indexOf("上班") == -1; if (findNoPeriod2(s, isVacation) && findNoPeriod(s, isVacation)) { Matcher dtm = dateTime.matcher(s); while (dtm.find()) { if (isVacation) { vacations.add(getDateStr(Integer.parseInt(dtm.group(1)), Integer.parseInt(dtm.group(2)))); } else { workDays.add(getDateStr(Integer.parseInt(dtm.group(1)), Integer.parseInt(dtm.group(2)))); } } } } } private boolean findNoPeriod2(String s, boolean isVacation) { Matcher dtp2m = dateTimePeriod2.matcher(s); if (dtp2m.find()) { addPeriodToSet(dtp2m.group(1), dtp2m.group(2), dtp2m.group(3), dtp2m.group(4), isVacation ? vacations : workDays); return false; } return true; } private boolean findNoPeriod(String s, boolean isVacation) { Matcher dtp2m = dateTimePeriod.matcher(s); if (dtp2m.find()) { addPeriodToSet(dtp2m.group(1), dtp2m.group(2), dtp2m.group(1), dtp2m.group(3), isVacation ? vacations : workDays); return false; } return true; } private void addPeriodToSet(String stM, String stD, String edM, String edD, Set set) { Calendar st = Calendar.getInstance(); st.set(Integer.parseInt(year), Integer.parseInt(stM) - 1, Integer.parseInt(stD)); Calendar ed = (Calendar) st.clone(); ed.set(Integer.parseInt(year), Integer.parseInt(edM) - 1, Integer.parseInt(edD)); while (ed.after(st)) { set.add(getDateStr(st)); st.add(Calendar.DATE, 1); } set.add(getDateStr(ed)); } private String getDateStr(Calendar c) { return getDateStr(c.get(Calendar.MONTH) + 1, c.get(Calendar.DATE)); } private String getDateStr(int m, int d) { StringBuilder sb = new StringBuilder(year); if (m < 10) { sb.append(0); } sb.append(m); if (d < 10) { sb.append(0); } sb.append(d); return sb.toString(); } }