美文网首页
java htmlUnit爬虫日历

java htmlUnit爬虫日历

作者: wsj1211 | 来源:发表于2022-03-09 23:30 被阅读0次

    爬取www.wannianli.tianqi.com

    
    // 模仿点击类
        public HtmlPage getDateHtml(HtmlPage page, String btn) throws IOException {
            HtmlSelect select = (HtmlSelect) page.getElementById("month_select");
            HtmlPage hp = select.click();
            HtmlAnchor anchor = (HtmlAnchor) page.getByXPath(btn).get(0);
            anchor.click();
            return hp;
        }
    // webClient 工具类
    package org.rcisoft.internal.core.util.webClient;
    
    import com.gargoylesoftware.htmlunit.BrowserVersion;
    import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
    import com.gargoylesoftware.htmlunit.WebClient;
    import org.springframework.stereotype.Component;
    
    import java.security.GeneralSecurityException;
    
    @Component
    public class ThreadLocalClientFactory {
    
        //单例工厂模式
        private final static ThreadLocalClientFactory instance =new ThreadLocalClientFactory();
    
        public static ThreadLocalClientFactory getInstance(){
            return instance;
        }
    
    
    
        // 覆写ThreadLocal的initialValue方法
        //线程的本地实例存储器,用于存储WebClient实例
        private ThreadLocal<WebClient> client = new ThreadLocal<WebClient>() {
    
            @Override
            //该方法ThreadLocal变量第一次get的时候执行,如果该线程已经执行过set方法,initialValue不会执行
            protected synchronized WebClient initialValue(){
                WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3);
    
                //设置webClient的相关参数
                webClient.getCookieManager().setCookiesEnabled(true);// 开启cookie管理
                webClient.setJavaScriptEnabled(true);// 开启js解析
                webClient.setCssEnabled(false);
                webClient.setThrowExceptionOnFailingStatusCode(true);
    //            webClient.setThrowExceptionOnScriptError(true);
                // 当出现Http error时,程序不抛异常继续执行
                webClient.setThrowExceptionOnFailingStatusCode(false);
                // 防止js语法错误抛出异常
                webClient.setThrowExceptionOnScriptError(false); // js运行错误时,是否抛出异常
                try {
                    webClient.setUseInsecureSSL(true);
                } catch (GeneralSecurityException e) {
                    e.printStackTrace();
                }
                // 默认是false, 设置为true的话不让你的浏览行为被记录
    //            webClient.setDoNotTrackEnabled(false);
                // 设置Ajax异步处理控制器即启用Ajax支持
                webClient.setAjaxController(new NicelyResynchronizingAjaxController());
    
                return webClient;
            }
        };
    
    
        public void setWebClient(WebClient wc) {
            client.set(wc);
        }
    
        public WebClient getWebClient() {
            return client.get();
        }
    }
    
    
    // 主方法
        public Map<String, List<InHoliday>> getMonthHtml() throws Exception {
            long  startTime = System.currentTimeMillis();    //获取开始时间
            // 获取指定网页实体
            WebClient webClient = null;
            List<InHoliday> holidays = new ArrayList<>();
            try {
                webClient = localClientFactory.getWebClient();
                HtmlPage page = getHtmlPage(urlStr, webClient);
                HtmlSelect htmlSelect = (HtmlSelect) page.getElementById("month_select");
                int thisMonth = Integer.valueOf(htmlSelect.getDefaultValue()) + 1;
                int t = htmlSelect.getOptionSize();
                for (int i = thisMonth; i < htmlSelect.getOptionSize(); i++) {
                    page =  getDateHtml(page, "//*[@id=\"next_buttons\"]");
                    holidays.addAll(getHoliday(page));
                }
                page = getHtmlPage(urlStr, webClient);
                holidays.addAll(getHoliday(page));
                for (int i = thisMonth - 1; i > 0; i--) {
                    page = getDateHtml(page, "//*[@id=\"prev_buttons\"]");
                    holidays.addAll(getHoliday(page));
                }
            }catch (Exception e){
                throw new Exception(e.getMessage());
            }finally {
                webClient.closeAllWindows();
            }
    }
    
    // 返回节假日数据
      public List<InHoliday> getHoliday(HtmlPage page) throws IOException, ParseException {
            boolean isMultiHoliday = false;
            String otherHolidayName = "";
            String oneHolidayName = "";
            // 获取年月
            HtmlSelect htmlSelectM = (HtmlSelect) page.getElementById("month_select");
            HtmlSelect htmlSelectY = (HtmlSelect) page.getElementById("year_select");
            int thisMonth = Integer.valueOf(htmlSelectM.getDefaultValue()) + 1;
            int thisYear = Integer.valueOf(htmlSelectY.getDefaultValue());
            // 定义返回集合
            List<InHoliday> holidays = new ArrayList<>();
            //获取日历表格tbody
            DomElement anchor = page.getElementsByTagName("tbody").get(0);
            //获取 行
            DomNodeList<HtmlElement> anchor1 = anchor.getElementsByTagName("tr");
            // 遍历行
            for (HtmlElement htmlElement : anchor1) {
                // 获取列
                DomNodeList<HtmlElement> anchor2 = htmlElement.getElementsByTagName("td");
                // 遍历列
                for (HtmlElement element : anchor2) {
                    if (element.asXml().contains("before")){
                        continue;
                    };
                    if (element.asXml().contains("after")){
                        break;
                    }
                    HtmlElement domElement = element.getElementsByTagName("div").get(0);
                    List<String> dateDetail = Arrays.asList(domElement.asText().split("\r\n"));
                    if ("休".equals(dateDetail.get(0)) || "班".equals(dateDetail.get(0))) {
                        InHoliday inHoliday = new InHoliday();
                        String holidayDate = thisYear + "-" + thisMonth + "-" + dateDetail.get(1);
                        inHoliday.setHolidayDate(DateUtil.parse(holidayDate));
                        inHoliday.setHolidayYear(String.valueOf(thisYear));
                        inHoliday.setIsHoliday(1);
                        inHoliday.setMultipleSalary("1");
                        if ("休".equals(dateDetail.get(0))) {
                            inHoliday.setWorkType(WorkTypeEnums.REST.getCode());
                        }else if ("班".equals(dateDetail.get(0))){
                            inHoliday.setWorkType(WorkTypeEnums.WORK.getCode());
                        }
                        if (null!= dateDetail.get(2) && dateDetail.get(2).contains("节")){
                            inHoliday.setWorkType(WorkTypeEnums.HOLIDAY.getCode());
                            oneHolidayName = dateDetail.get(2);
                            inHoliday.setHolidayName(dateDetail.get(2));
                        }else {
                            // 查询今日是否是农历节日
                            // 将日期转成农历
                            SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                            Calendar date = Calendar.getInstance();
                            date.setTime(chineseDateFormat.parse(holidayDate));
                            String lunarTime = new LunarUtil(date).toString();
                            String lunar = lunarTime.split("-")[1].length() <=1 ?
                                    lunarTime.split("-")[0] + "0"+ lunarTime.split("-")[1]: lunarTime.replaceAll("-","");
                            for (String o : lFtv) {
                                if (o.contains(lunar)) {
                                    // 本月有多个节日 给本月上个节日附属休息调休等赋节日名称值
                                    if (StringUtils.isNotBlank(oneHolidayName)) {
                                        for (InHoliday holiday : holidays) {
                                            if (StringUtils.isBlank(holiday.getHolidayName()) &&
                                                    DateUtil.between(holiday.getHolidayDate(), inHoliday.getHolidayDate(), DateUnit.DAY) > 7) {
                                                holiday.setHolidayName(oneHolidayName);
                                            }
                                        }
                                    }
                                    oneHolidayName = o.split("/")[1];
                                    inHoliday.setHolidayName(o.split("/")[1]);
                                    inHoliday.setIsHoliday(0);
                                    break;
                                }
                            }
                            // 查询今日是否是阳历节日
                            String sLunar = (thisMonth) + (dateDetail.get(1).length() <= 1 ? "0" + dateDetail.get(1) : dateDetail.get(1));
                            for (String o : sFtv) {
                                if (o.contains(sLunar)) {
                                    if (StringUtils.isBlank(inHoliday.getHolidayName())) {
                                        oneHolidayName = o.split("/")[1];
                                        inHoliday.setHolidayName(o.split("/")[1]);
                                        inHoliday.setIsHoliday(0);
                                    } else {
                                        isMultiHoliday = true;
                                        otherHolidayName = o.split("/")[1];
                                    }
                                    break;
                                }
                            }
                        }
    
                        holidays.add(inHoliday);
                    }
                }
            }
            // 判断是否有重复节日
            List<InHoliday> otherHolidays = new ArrayList<>();
            for (int i = 0;i< holidays.size();i++) {
                if (StringUtils.isBlank(holidays.get(i).getHolidayName())
                        && (i -1 >=0 && DateUtil.between(holidays.get(i).getHolidayDate(),holidays.get(i-1).getHolidayDate(),DateUnit.DAY) <7) ) {
                    holidays.get(i).setHolidayName(oneHolidayName);
                }
                if (isMultiHoliday) {
                    InHoliday inHoliday = new InHoliday();
                    BeanUtil.copyProperties(holidays.get(i), inHoliday);
                    inHoliday.setHolidayName(otherHolidayName);
                    otherHolidays.add(inHoliday);
                }
            }
            holidays.addAll(otherHolidays);
            return holidays;
    
        }
    
        //农历节日
        static List<String> lFtv = Arrays.asList(
                "0101/春节",
                "0115/元宵节",
                "0505/端午节",
                "0815/中秋节"
        );
        //阳历节日
        static List<String> sFtv = Arrays.asList(
                "0101/元旦",
                "0501/劳动节",
                "1001/国庆节"
        );
    
    

    webClient 常用方法

    int getHistoryPageCacheLimit() //返回在历史中缓存的最大页数。

    int getHistorySizeLimit()             //返回最大页数保持在历史记录。
    
    String getHomePage()              //返回客户端当前的主页。
    
    String getHomePage()              //返回客户端当前的主页。
    
    String getHomePage()              //返回客户端当前的主页。
    
    String getHomePage()              //返回客户端当前的主页。
    
    int getMaxInMemory()             //返回内存中的最大字节,然后将内容保存到文件中
    
    ProxyConfig getProxyConfig()              //返回此客户机的代理配置
    
    int getScreenHeight()              //返回屏幕高度。
    
    int getScreenWidth()            //返回屏幕宽度。
    
    char[] getSSLClientCertificatePassword()              //   得到sslclientcertificatepassword
    
    String[] getSSLClientCipherSuites()             //获取在SSL连接上启用的密码套件。
    
    String[] getSSLClientProtocols()             //获取在SSL连接上启用的协议版本
    
    KeyStore getSSLClientCertificateStore()              //得到sslclientcertificatestore。
    
    String getSSLInsecureProtocol()              //得到了SSL协议,可用于只有当setuseinsecuressl(布尔)设置为true。
    
    KeyStore getSSLTrustStore()             //获取SSL信任库。
    
    int getTimeout()            //获取该程序的超时值
    
    int getWebSocketMaxBinaryMessageBufferSize()
    
    int getWebSocketMaxBinaryMessageSize()
    
    int getWebSocketMaxTextMessageBufferSize()
    
    int getWebSocketMaxTextMessageSize()
    
    boolean isActiveXNative()                   //返回是否允许本地ActiveX组件
    
    boolean isAppletEnabled()             //如果启用了applet,则返回true
    
    boolean isCssEnabled()            //如果CSS启用,则返回true。
    
    boolean isDoNotTrackEnabled()            //如果“不跟踪”启用,则返回true。
    
    boolean isDownloadImages()             //返回是否自动下载默认的图像,或不。
    
    boolean isGeolocationEnabled()            //如果定位是使返回true。
    
    boolean isJavaScriptEnabled()              //如果启用了JavaScript并成功地加载脚本引擎,则返回true。
    
    boolean isPopupBlockerEnabled()              //如果启用了弹出窗口拦截器,则返回true
    
    boolean isPrintContentOnFailingStatusCode()             //如果结果文档的内容在失败的响应代码中被打印到控制台,则返回true。
    
    boolean isRedirectEnabled()              //返回是否重定向之后将自动从服务器收到一个重定向状态代码。
    
    boolean isThrowExceptionOnFailingStatusCode()              //如果在响应码失败时抛出异常,则返回true
    
    boolean isThrowExceptionOnScriptError()           //指示当脚本执行失败(默认)或是否应捕获并仅记录以允许页执行继续时,是否应该抛出异常。
    
    boolean isUseInsecureSSL()           //指示是否应该使用不安全的SSL。
    
    void setAppletEnabled(boolean enabled)             //启用/禁用applet支持。
    
    void setCssEnabled(boolean enabled)             //启用/禁用CSS支持。
    
    void setDoNotTrackEnabled(boolean enabled)            //启用/禁用“不跟踪”支持
    
    void setDownloadImages(boolean downloadImages)           //设置是否自动下载默认图像,或不。
    
    void setGeolocationEnabled(boolean enabled)            //启用/禁用地理定位支持
    
    void setHistoryPageCacheLimit(int historyPageCacheLimit)           //设置历史中缓存的最大页数
    
    void setHistorySizeLimit(int historySizeLimit)              //设置历史大小限制
    
    void setHomePage(String homePage)           //设置客户端主页。
    
    void setJavaScriptEnabled(boolean enabled)           //启用/禁用JavaScript支持。
    
    void setLocalAddress(InetAddress localAddress)            //设置用于请求执行的本地地址
    
    void setMaxInMemory(int maxInMemory)          //设置内存中的最大字节,然后将内容保存到文件中。
    
    void setPopupBlockerEnabled(boolean enabled)            //启用/禁用弹出窗口拦截器
    
    void setPrintContentOnFailingStatusCode(boolean enabled)          //指定在失败的响应代码的情况下,结果文档的内容是否会被打印到控制台中
    
    void setProxyConfig(ProxyConfig proxyConfig)               //集代理配置为在这个客户端
    
    void setRedirectEnabled(boolean enabled)          //是否或不设置自动重定向将在随后的一redirect券代码从服务器的状态。
    
    void setScreenHeight(int screenHeight)           //设置屏幕的高度。
    
    void setScreenWidth(int screenWidth)           //设置屏幕宽度。
    
    void setSSLClientCertificate(InputStream certificateInputStream, String certificatePassword, String certificateType)         //SSL客户端证书的使用。
    
    
    
    void setSSLClientCipherSuites(String[] sslClientCipherSuites)            //设置启用SSL连接的密码套件,NULL使用默认的套件。
    
    void setSSLClientProtocols(String[] sslClientProtocols)          //设置启用SSL连接的协议版本,NULL使用默认版本。
    
    void setSSLInsecureProtocol(String sslInsecureProtocol)            //设置SSL协议,只有当setuseinsecuressl(布尔)设置为true
    
    void setSSLTrustStore(URL sslTrustStoreUrl, String sslTrustStorePassword, String sslTrustStoreType)           //设置SSL服务器证书信任存储区。
    
    
    void setThrowExceptionOnFailingStatusCode(boolean enabled)           //指定是否在出现故障状态代码时抛出异常
    
    void setThrowExceptionOnScriptError(boolean enabled)           //改变该WebClient行为脚本时出现错误
    
    void setTimeout(int timeout)            //设置该程序的超时。
    
    void setUseInsecureSSL(boolean useInsecureSSL)         //如果设置为true,客户机将接受与任何主机的连接,而不管它们是否有有效证书
    

    常用方法

    HtmlPage page = webClient.getPage(url); // 抓取页面

    webClient.close(); //关闭模拟的窗口

    void addCookie(String cookieString, URL pageUrl, Object origin); //解析给定的cookie并将其添加到我们的cookie存储库。

    AjaxController getAjaxController(); //获取当前Ajax控制器。

    BrowserVersion getBrowserVersion(); //返回当前浏览器版本。

    Cache getCache() //获取当前正在使用的缓存。

    WebWindow getCurrentWindow() //返回此客户端的“当前”窗口。

    HTMLParserListener getHTMLParserListener() //获取由html解析器生成的消息的配置侦听器。

    WebWindow getCurrentWindow() //返回此客户端的“当前”窗口

    相关文章

      网友评论

          本文标题:java htmlUnit爬虫日历

          本文链接:https://www.haomeiwen.com/subject/xmqpmktx.html