JAVA爬虫三大运营商

此代码仅供个人学习、研究之用,请勿用于商业用途

移动采集


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.util.Cookie;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * cmcc
 *
 */

@Service("cmccService")
public class CmccServiceImpl implements CmccService {
   

    private static Pattern NUMBER_PATTERN = Pattern.compile("totalNum\":(.*?),");
    protected Logger log = LoggerFactory.getLogger(getClass());

    @Override
    public String fetchLoginSms(String data, HttpServletRequest request) throws Exception {
   
        JSONObject json = new JSONObject();
        String decryptedData = RsaUtil.privateDecrypt(data, RsaUtil.getPrivateKey(RsaUtil.PRIVATE_KEY));
        if (null == decryptedData && "".equals(decryptedData)) {
   
            json.put("msg", "参数错误");
            json.put("code", "0001");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }
        JSONObject jsonData = JSONObject.parseObject(decryptedData);
        String phone = jsonData.getString("phone");
        if (phone == null) {
   
            json.put("msg", "手机号码不能为空");
            json.put("code", "0001");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }
        String custId = jsonData.getString("custId");
        if (custId == null) {
   
            json.put("msg", "custId不能为空");
            json.put("code", "0002");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }
        return getLoginSms(phone, request, custId);
    }

    private String getLoginSms(String phone, HttpServletRequest request, String custId) throws Exception {
   
        JSONObject json = new JSONObject();
        WebClient webClient = new WebClient(BrowserVersion.CHROME);
        webClient.getOptions().setCssEnabled(false);
        webClient.getOptions().setUseInsecureSSL(true);
        webClient.getOptions().setActiveXNative(false);
        webClient.getOptions().setJavaScriptEnabled(true);
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);

        log.info("登录 用户 [{}] 开始获取登录验证码", phone);

        Map<String, String> header = new HashMap(10);
        header.put("Accept", "application/json, text/javascript, */*; q=0.01");
        header.put("Referer", "https://login.10086.cn/login.html");
        header.put("X-Requested-With", "XMLHttpRequest");
        String url = "https://login.10086.cn/login.html";
        WebRequest webRequest = new WebRequest(new URL(url), HttpMethod.GET);
        webRequest.setAdditionalHeaders(header);
        webClient.getPage(webRequest);

        int retryCount = 1;
        do {
   
            if (retryCount > 1) {
   
                Thread.sleep(60000);
            }
            log.info("登录 用户 [{}] 第 [{}] 次获取登录验证码中...", phone, retryCount);
            List<NameValuePair> reqParam = new ArrayList();
            reqParam.clear();
            reqParam.add(new NameValuePair("userName", phone));
            webRequest = new WebRequest(new URL("https://login.10086.cn/chkNumberAction.action"), HttpMethod.POST);
            webRequest.setRequestParameters(reqParam);
            TextPage sendSMS = webClient.getPage(webRequest);
            log.info("登录 用户 [{}] 获取手机验证码第一步结果: [{}]", phone, sendSMS.getContent());
            if ("true".equals(sendSMS.getContent())) {
   
                log.info("登录 用户 [{}] 获取手机验证码第二步开始:", phone);
                retryCount++;
                json = getLoginSmsSecond(webClient, phone, request, custId);
            } else {
   
                json.put("msg", "发送验证码失败,请稍后再试!");
                json.put("code", "0002");
                json.put("data", "error");
                return JSONObject.toJSONString(json);
            }
        } while (!"0000".equals(json.getString("code"))
                && !"0010".equals(json.getString("code"))
                && !"0011".equals(json.getString("code"))
                && !"1001".equals(json.getString("code"))
                && !"1010".equals(json.getString("code")));
        return JSONObject.toJSONString(json);
    }

    private JSONObject getLoginSmsSecond(WebClient webClient, String phone, HttpServletRequest request, String custId) throws Exception {
   
        JSONObject json = new JSONObject();
        List<NameValuePair> reqParam = new ArrayList();
        reqParam.add(new NameValuePair("userName", phone));
        WebRequest webRequest = new WebRequest(new URL("https://login.10086.cn/loadToken.action"), HttpMethod.POST);
        webRequest.setRequestParameters(reqParam);
        Page codePage = webClient.getPage(webRequest);
        JSONObject codePageJson = JSONObject.parseObject(codePage.getWebResponse().getContentAsString());
        log.info("登录 用户 [{}] 获取手机验证码第二步结果: [{}]", phone, codePageJson);
        if (!codePage.getWebResponse().getContentAsString().contains("\"code\":\"0000\",\"desc\":\"成功\"")) {
   
            json.put("msg", "发送验证码失败,请重试");
            json.put("code", "0003");
            json.put("data", "error");
            return json;
        }
        String tokenResult = codePageJson.getString("result");
        return getLoginThird(webClient, phone, tokenResult, request, custId);
    }

    private JSONObject getLoginThird(WebClient webClient, String phone, String tokenResult, HttpServletRequest request, String custId) throws Exception {
   
        JSONObject json = new JSONObject();

        Map<String, String> header = new HashMap(10);
        header.put("Content-Type", "application/x-www-form-url1encoded; charset=UTF-8");
        header.put("Referer", "https://login.10086.cn/login.html?channelID=12034&backUrl=http%3A%2F%2Fservice.jx.10086.cn%2Fservice%2Fresources%2FindexNew.html");
        WebRequest webRequest = new WebRequest(new URL("https://login.10086.cn/sendflag.htm?timestamp=" + System.currentTimeMillis()), HttpMethod.POST);
        webRequest.setAdditionalHeaders(header);
        webClient.getPage(webRequest);
        Cookie cookie = webClient.getCookieManager().getCookie("sendflag");
        if (null != cookie) {
   
            String sendflag = cookie.getValue();
            log.info("登录 用户 [{}] 获取Cookie: sendflag 成功: [{}]", phone, sendflag);
        }

        header.put("Xa-before", tokenResult);
        header.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

        List<NameValuePair> reqParam = new ArrayList();
        reqParam.add(new NameValuePair("userName", phone));
        reqParam.add(new NameValuePair("channelID", "12003"));
        reqParam.add(new NameValuePair("type", "01"));

        webRequest = new WebRequest(new URL("https://login.10086.cn/sendRandomCodeAction.action"), HttpMethod.POST);
        webRequest.setRequestParameters(reqParam);
        webRequest.setAdditionalHeaders(header);

        Page resultPage = webClient.getPage(webRequest);
        log.info("登录 用户 [{}] 获取验证码第三步结果: [{}]", phone, resultPage.getWebResponse().getContentAsString());
        if ("1".equals(resultPage.getWebResponse().getContentAsString())) {
   
            log.info("登录 用户 [{}] 获取登录验证码频繁,等待1分钟后重新发送!", phone);
            json.put("msg", "对不起,短信随机码暂时不能发送,等待1分钟后重新发送!");
            json.put("code", "0010");
            json.put("data", "error");
            return json;
        } else if (resultPage.getWebResponse().getContentAsString().contains("0")) {
   
            log.info("登录 用户 [{}] 短信验证码发送成功!", phone);
            json.put("msg", "短信验证码发送成功");
            json.put("code", "0000");
            json.put("data", "success");
            request.getSession().setAttribute(custId + "loginSms", webClient);
            return json;
        } else if (resultPage.getWebResponse().getContentAsString().contains("2")) {
   
            log.info("登录 用户 [{}] 获取短信验证码次数到达上限,请24小时后再试", phone);
            json.put("msg", "获取短信验证码次数到达上限,请24小时后再试!");
            json.put("code", "0011");
            json.put("data", "error");
            return json;
        } else if (resultPage.getWebResponse().getContentAsString().contains("6")) {
   
            log.info("登录 用户 [{}] 获取短信验证码失败,官网响应为6,重试中...", phone);
            json.put("msg", "获取短信验证码失败,官网响应为6,重试中!");
            json.put("code", "0012");
            json.put("data", "error");
            return json;
        } else if (resultPage.getWebResponse().getContentAsString().contains("error")){
   
            log.info("登录 用户 [{}] 获取短信验证码失败,手机号码有误:[{}] ,请重试...", phone, resultPage.getWebResponse().getContentAsString());
            json.put("msg", "获取短信验证码失败,手机号码有误");
            json.put("code", "1001");
            json.put("data", "error");
            return json;
        }else {
   
            log.info("登录 用户 [{}] 获取短信验证码失败,系统异常:[{}] ,重试中...", phone, resultPage.getWebResponse().getContentAsString());
            json.put("msg", "获取短信验证码失败,系统异常,重试中!");
            json.put("code", "1000");
            json.put("data", "error");
            return json;
        }
    }

    @Override
    public String loginBySms(String data, HttpServletRequest request) throws Exception {
   
        JSONObject json = new JSONObject();
        String decryptedData = RsaUtil.privateDecrypt(data, RsaUtil.getPrivateKey(RsaUtil.PRIVATE_KEY));
        if (decryptedData == null && "".equals(decryptedData)) {
   
            json.put("msg", "参数不能为空");
            json.put("code", "2000");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }
        JSONObject jsonData = JSONObject.parseObject(decryptedData);
        if (jsonData.getString("phone") == null) {
   
            json.put("msg", "手机号不能为空!");
            json.put("code", "2001");
            json.put("data", "error");
        }
        if (jsonData.getString("smsCode") == null) {
   
            json.put("msg", "短信验证码不能为空!");
            json.put("code", "2001");
            json.put("data", "error");
        }
        if (jsonData.getString("custId") == null) {
   
            json.put("msg", "custId不能为空!");
            json.put("code", "2001");
            json.put("data", "error");
        }
        return JSONObject.toJSONString(cmccLogin(jsonData.getString("phone"), jsonData.getString("smsCode"), jsonData.getString("custId"), request));
    }

    private JSONObject cmccLogin(String phone, String smsCode, String custId, HttpServletRequest request) throws Exception {
   
        WebClient webClient = (WebClient) request.getSession().getAttribute(custId + "loginSms");
        Map<String, String> header = new HashMap(10);
        List<NameValuePair> reqParam = new ArrayList();
        JSONObject json = new JSONObject();
        WebRequest webRequest = new WebRequest(new URL("https://login.10086.cn/login.htm"), HttpMethod.GET);
        header.put("Accept", "application/json, text/javascript, */*; q=0.01");
        header.put("Accept-Encoding", "gzip, deflate, br");
        header.put("Accept-Language", "zh-CN,zh;q=0.9");
        header.put("Connection", "keep-alive");
        header.put("Host", "login.10086.cn");
        header.put("Referer", "https://login.10086.cn/login.html");
        header.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36");
        header.put("X-Requested-With", "XMLHttpRequest");
        webRequest.setAdditionalHeaders(header);
        webRequest.setCharset(StandardCharsets.UTF_8);
        reqParam.clear();
        reqParam.add(new NameValuePair("accountType", "01"));
        reqParam.add(new NameValuePair("account", phone));
        reqParam.add(new NameValuePair("password", smsCode));
        reqParam.add(new NameValuePair("pwdType", "02"));
        reqParam.add(new NameValuePair("smsPwd", smsCode));
        reqParam.add(new NameValuePair("inputCode", ""));
        reqParam.add(new NameValuePair("backUrl", "http%3A%2F%2Fwww.10086.cn%2Froaming%2Fyewu%2Findex%2Fsn%2F%3FWT.mc_id%3DBD000GJMY_YEWU_GJC_1_190626"));
        reqParam.add(new NameValuePair("rememberMe", "0"));
        reqParam.add(new NameValuePair("channelID", "12034"));
        reqParam.add(new NameValuePair("loginMode", "01"));
        reqParam.add(new NameValuePair("protocol", "https%3A"));
        reqParam.add(new NameValuePair("timestamp", String.valueOf(System.currentTimeMillis())));
        webRequest.setRequestParameters(reqParam);
        Page loginResultPage = null;
        try {
   
            loginResultPage = webClient.getPage(webRequest);
        } catch (NullPointerException e) {
   
            json.put("msg", "官网响应为空!");
            json.put("code", "9999");
            json.put("data", "error");
            return json;
        }
        if (loginResultPage.getWebResponse().getContentAsString().contains("认证成功")) {
   
            json.put("msg", "登录成功!");
            json.put("code", "0000");
            json.put("data", "success");
            log.info("登录 用户 [{}] 登录成功,页面跳转中!", phone);
            JSONObject info = JSONObject.parseObject(loginResultPage.getWebResponse().getContentAsString());
            String artifact = info.getString("artifact");
            jumpAfterSuccessLogin(webClient, artifact, custId, request);
            log.info("登录 用户 [{}] 登录成功,跳转完成!", phone);
        } else if (loginResultPage.getWebResponse().getContentAsString().contains("密码锁定")) {
   
            json.put("msg", "登录失败,密码锁定!");
            json.put("code", "2002");
            json.put("data", "error");
            log.info("登录 用户 [{}] 登录失败! 登录密码被锁定!", phone);
        } else if (loginResultPage.getWebResponse().getContentAsString().contains("账号锁定")) {
   
            json.put("msg", "登录失败,账号锁定!");
            json.put("code", "2003");
            json.put("data", "error");
            log.info("登录 用户 [{}] 登录失败! 登录账号被锁定!", phone);
        } else if (loginResultPage.getWebResponse().getContentAsString().contains("系统繁忙")) {
   
            json.put("msg", "登录失败,官网系统繁忙!");
            json.put("code", "2004");
            json.put("data", "error");
            log.info("登录 用户 [{}] 登录失败! 官网系统繁忙,请重试!", phone);
        } else if (loginResultPage.getWebResponse().getContentAsString().contains("您的账户名与密码不匹配")) {
   
            json.put("msg", "登录失败,您的账户名与密码不匹配!");
            json.put("code", "2005");
            json.put("data", "error");
            log.info("用户 [{}] 登录失败! 账户名与密码不匹配!", phone);
        } else if (loginResultPage.getWebResponse().getContentAsString().contains("短信随机码不正确或已过期")) {
   
            json.put("msg", "登录失败,短信随机码不正确或已过期!");
            json.put("code", "2006");
            json.put("data", "error");
            log.info("用户 [{}] 登录失败! 短信随机码不正确或已过期!", phone);
        } else if (loginResultPage.getWebResponse().getContentAsString().contains("请您输入正确的密码")) {
   
            json.put("msg", "登录失败,请您输入正确的密码!");
            json.put("code", "2007");
            json.put("data", "error");
            log.info("登录 用户 [{}] 登录失败! 请您输入正确的密码!", phone);
        } else {
   
            json.put("msg", "登录失败,未知异常!");
            json.put("code", "2008");
            json.put("data", "error");
            log.info("登录 用户 [{}] 登录失败! 未知异常: [{}]", phone, loginResultPage.getWebResponse().getContentAsString());
        }
        return json;
    }

    private void jumpAfterSuccessLogin(WebClient webClient, String artifact, String custId, HttpServletRequest request) throws Exception {
   

        String url = "http://shop.10086.cn/i/v1/auth/getArtifact?backUrl=http%3A%2F%2Fshop.10086.cn%2Fi%2F&artifact=" + artifact;
        WebRequest webRequest = new WebRequest(new URL(url), HttpMethod.GET);
        webClient.getPage(webRequest);
        log.info("用户登录成功,页面跳转中(1/3)...");

        url = "https://login.10086.cn/SSOCheck.action?channelID=12003&backUrl=http://shop.10086.cn/i/?f=home";
        webRequest = new WebRequest(new URL(url), HttpMethod.GET);
        webClient.getPage(webRequest);
        log.info("用户登录成功,页面跳转中(2/3)...");

        url = "http://shop.10086.cn/i/?welcome=" + System.currentTimeMillis();
        webRequest = new WebRequest(new URL(url), HttpMethod.GET);
        webClient.getPage(webRequest);
        log.info("用户登录成功,页面跳转中(3/3)...");

        url = "http://shop.10086.cn/i/?f=billdetailqry";
        webRequest = new WebRequest(new URL(url), HttpMethod.GET);
        webClient.getPage(webRequest);

        request.getSession().setAttribute(custId, webClient);
        request.getSession().setAttribute(custId + "bill", webClient);

    }

    @Override
    public String fetchXDBySms(String data, HttpServletRequest request) throws Exception {
   
        JSONObject json = new JSONObject();
        String decryptedData = RsaUtil.privateDecrypt(data, RsaUtil.getPrivateKey(RsaUtil.PRIVATE_KEY));
        if (decryptedData == null && "".equals(decryptedData)) {
   
            json.put("msg", "参数不能为空");
            json.put("code", "2000");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }
        JSONObject jsonData = JSONObject.parseObject(decryptedData);
        if (jsonData.getString("phone") == null) {
   
            json.put("msg", "手机号不能为空!");
            json.put("code", "2001");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }

        WebClient webClient = (WebClient) request.getSession().getAttribute(jsonData.getString("custId"));
        if (null == webClient) {
   
            json.put("msg", "非法请求!");
            json.put("code", "9999");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }
        Map<String, String> header = new HashMap(10);
        header.put("Referer", "http://shop.10086.cn/i/?f=billdetailqry");
        WebRequest webRequest = new WebRequest(new URL("http://shop.10086.cn/i/apps/serviceapps/billdetail/showvec.html"), HttpMethod.GET);
        webRequest.setAdditionalHeaders(header);
        webRequest.setCharset(StandardCharsets.UTF_8);
        webClient.getPage(webRequest);
        log.info("详单 用户 [{}] 获取详单验证码第一步完成", jsonData.getString("phone"));

        log.info("详单 用户 [{}] 获取详单验证码前等待20秒,避免操作频繁", jsonData.getString("phone"));
        for (int i = 0; i < 8; i++) {
   
            Thread.sleep(1000);
        }

        log.info("详单 用户 [{}] 获取详单验证码第二步开始", jsonData.getString("phone"));
        return JSONObject.toJSONString(fetchXDBySmsSecond(webClient, jsonData));
    }

    private JSONObject fetchXDBySmsSecond(WebClient webClient, JSONObject jsonData) throws Exception {
   
        Map<String, String> header = new HashMap(10);
        JSONObject json = new JSONObject();
        int retryCount = 1;
        Page sendSMSResult = null;
        do {
   
            log.info("详单 用户 [{}] 开始第 [{}] 次获取详单验证码", jsonData.getString("phone"), retryCount);
            String url = String.format("https://shop.10086.cn/i/v1/fee/detbillrandomcodejsonp/%s?callback=jQuery011591518200914375_%s&_=%s",
                    jsonData.getString("phone"), System.currentTimeMillis(), System.currentTimeMillis());
            header.clear();
            header.put("Referer", "https://shop.10086.cn/i/?f=home&welcome=" + Calendar.getInstance().getTimeInMillis());
            WebRequest webRequest = new WebRequest(new URL(url), HttpMethod.GET);
            webRequest.setCharset(StandardCharsets.UTF_8);
            webRequest.setAdditionalHeaders(header);
            sendSMSResult = webClient.getPage(webRequest);
            log.info("详单 用户 [{}] 第 [{}] 次获取详单验证码结果: [{}]", jsonData.getString("phone"),
                    retryCount, sendSMSResult.getWebResponse().getContentAsString());
            retryCount++;
        } while (retryCount >= 3 && sendSMSResult.getWebResponse().getContentAsString().contains("\"retMsg\":\"success\""));

        if (sendSMSResult != null) {
   
            if (sendSMSResult.getWebResponse().getContentAsString().contains("下发短信次数过多")) {
   
                json.put("msg", "下发短信次数过多");
                json.put("code", "3001");
                json.put("data", "error");
                log.info("详单 用户 [{}] 发送详单验证码失败,下发短信次数过多,请 [{}] 小时后再试!", jsonData.getString("phone"), "24");
            } else if (sendSMSResult.getWebResponse().getContentAsString().contains("尊敬的用户,请勿在1分钟内重复下发短信")) {
   
                json.put("msg", "请勿在1分钟内重复下发短信");
                json.put("code", "3002");
                json.put("data", "error");
                log.info("详单 用户 [{}] 发送详单验证码失败,请勿在1分钟内重复下发短信,请稍后再试!", jsonData.getString("phone"));
            } else if (sendSMSResult.getWebResponse().getContentAsString().contains("session信息为空,请先登录")) {
   
                json.put("msg", "session信息为空,请先登录");
                json.put("code", "3003");
                json.put("data", "error");
                log.info("详单 用户 [{}] 发送详单验证码失败,请先登录!", jsonData.getString("phone"));
            } else if (sendSMSResult.getWebResponse().getContentAsString().contains("\"retMsg\":\"success\"")) {
   
                json.put("msg", "详单短信验证码发送成功");
                json.put("code", "0000");
                json.put("data", "success");
                log.info("详单 用户 [{}] 发送详单验证码成功!", jsonData.getString("phone"));
            } else {
   
                json.put("msg", "发送失败,未知异常");
                json.put("code", "3004");
                json.put("data", "error");
                log.info("详单 用户 [{}] 发送详单验证码失败,异常原因: [{}]", jsonData.getString("phone"), sendSMSResult.getWebResponse().getContentAsString());
            }
        }
        return json;
    }

    @Override
    public String fetchImgCode(String dataStr, HttpServletRequest request) throws Exception {
   
        JSONObject json = new JSONObject();
        String decryptedData = RsaUtil.privateDecrypt(dataStr, RsaUtil.getPrivateKey(RsaUtil.PRIVATE_KEY));
        if (decryptedData == null && "".equals(decryptedData)) {
   
            json.put("msg", "参数错误");
            json.put("code", "0001");
            json.put("data", "error");
            return JSONObject.toJSONString(json);
        }
        JSONObject jsonData = JSONObject.parseObject(decryptedData);
        String custId = jsonData.getString("custId");

        WebClient webClient = (WebClient) request.getSession().getAttribute(custId);

        JSONObject data = new JSONObject();
        Map<String, String> header = new HashMap(10);
        header.put("Referer", "http://shop.10086.cn/i/?welcome=" + System.currentTimeMillis());
        String imgUrl = "http://shop.10086.cn/i/authImg?t=" + Math.</
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值