java htmlUnit爬虫日历

2022-03-09  本文已影响0人  wsj1211

爬取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() //返回此客户端的“当前”窗口

上一篇下一篇

猜你喜欢

热点阅读