【java爬虫】HttpClient4.5模拟登录知乎

0.关于HttpClient

虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

  1. 实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
  2. 支持自动重定向
  3. 支持 HTTPS 协议
  4. 支持代理服务器等

1.HttpClient4.5模拟登录网站步骤

  • 创建CloseHttpClient和HttpClientContext对象
  • 创建HttpPost(类似http中的post请求)对象
  • 添加请求参数到HttpPost对象中
  • 执行请求
  • 登录成功

由于网站模拟登录都会有验证码,关于验证码的处理一般有以下两种方式:

  1. 验证码识别接口(大多都是收费的),这种情况适合大规模登录。
  2. 将验证码下载到本地,手动输入验证码(以下例子采用这种方式)。

2.模拟登录的分析过程

  • 浏览器访问知乎 - 与世界分享你的知识、经验和见解知乎登录页面,然后右键审查元素(快捷键F12),选择network,把Preservre log选上,然后输入账号密码和验证码,点击登录。如果登录成功会重定向到知乎首页然后会有大量的请求了,这时找登录请求可能不方便。所以这里有个小技巧,故意把密码输错,这时候就不会重定向跳转了,就可以容易的找到登录请求。这里我用的邮箱登录。如下图

  • 现在要做的就是找到Form Data里面参数的来源,这里有4个参数分别是_xsrf,password,remember_me,email,_xsrf在登录页面源码里面能够找到,password就是你的密码,remember_me就是记住我那个复选框,email就是登录邮箱。经过测试_xsrf这个参数设置为“”空字符串也能登录成功,所以这个参数可以不用去获取。
  • 知乎登录的验证码。把验证码下载到本地,然后肉眼识别后手动输入。
  • 怎么验证是否成功登录知乎。提交登录请求后,知乎服务器会响应一段json,可以判断是否登录成功。

3.主要逻辑代码

以下是模拟登录知乎的主要逻辑代码
package com.wy;

import org.apache.http.NameValuePair;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.cookie.CookieSpecProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BestMatchSpecFactory;
import org.apache.http.impl.cookie.BrowserCompatSpecFactory;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 模拟登录知乎
 */
public class Main {
    //知乎首页
    final private static String INDEX_URL = "https://www.zhihu.com";
    //邮箱登录地址
    final private static String EMAIL_LOGIN_URL = "https://www.zhihu.com/login/email";
    //手机号码登录地址
    final private static String PHONENUM_LOGIN_URL = "https://www.zhihu.com/login/phone_num";
    //登录验证码地址
    final private static String YZM_URL = "https://www.zhihu.com/captcha.gif?type=login";

    private CloseableHttpClient httpClient;
    private HttpClientContext httpClientContext;

    /**
     * 初始化CloseableHttpClient、HttpClientContext并设置Cookie策略
     */
    public Main(){
        RequestConfig globalConfig = RequestConfig.custom()
                .setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY)
                .build();
        httpClient = HttpClients.custom()
                .setDefaultRequestConfig(globalConfig)
                .build();

        httpClientContext = HttpClientContext.create();
        Registry<CookieSpecProvider> registry = RegistryBuilder
                .<CookieSpecProvider> create()
                .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
                .register(CookieSpecs.BROWSER_COMPATIBILITY,
                        new BrowserCompatSpecFactory()).build();
        httpClientContext.setCookieSpecRegistry(registry);
    }
    /**
     *
     * @param emailOrPhoneNum 邮箱或手机号码
     * @param pwd 密码
     * @return
     */
    public boolean login(String emailOrPhoneNum,
                         String pwd){
        String yzm = null;
        String loginState = null;
        HttpGet getRequest = new HttpGet(INDEX_URL);
        HttpClientUtil.getWebPage(httpClient, httpClientContext, getRequest, "utf-8", false);
        HttpPost request = null;
        List<NameValuePair> formParams = new ArrayList<NameValuePair>();
        if(emailOrPhoneNum.contains("@")){
            //通过邮箱登录
            request = new HttpPost(EMAIL_LOGIN_URL);
            formParams.add(new BasicNameValuePair("email", emailOrPhoneNum));
        }
        else {
            //通过手机号码登录
            request = new HttpPost(PHONENUM_LOGIN_URL);
            formParams.add(new BasicNameValuePair("phone_num", emailOrPhoneNum));
        }
        yzm = yzm(httpClient, httpClientContext, YZM_URL);
        formParams.add(new BasicNameValuePair("captcha", yzm));
        formParams.add(new BasicNameValuePair("_xsrf", ""));//这个参数可以不用
        formParams.add(new BasicNameValuePair("password", pwd));
        formParams.add(new BasicNameValuePair("remember_me", "true"));
        UrlEncodedFormEntity entity = null;
        try {
            entity = new UrlEncodedFormEntity(formParams, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        request.setEntity(entity);
        loginState = HttpClientUtil.getWebPage(httpClient, httpClientContext, request, "utf-8", false);//登录
        JSONObject jo = new JSONObject(loginState);
        if(jo.get("r").toString().equals("0")){
            System.out.println("登录知乎成功");
            getRequest = new HttpGet("https://www.zhihu.com");
            /**
             * 访问首页
             */
            HttpClientUtil.getWebPage(httpClient, httpClientContext,getRequest, "utf-8", false);
            return true;
        }else{
            throw new RuntimeException(HttpClientUtil.decodeUnicode(loginState));
        }
    }
    /**
     * 下载验证码至本地,并手动输入验证码
     * @return
     */
    public String yzm(CloseableHttpClient httpClient,HttpClientContext context, String url){
        String verificationCodePath = System.getProperty("user.home");
        //下载验证码至本地
        HttpClientUtil.downloadFile(httpClient, context, url, verificationCodePath, "/yzm.jpg",true);
        System.out.println("请输入 " + verificationCodePath + "\\yzm.jpg 下的验证码:");
        Scanner sc = new Scanner(System.in);
        String yzm = sc.nextLine();
        return yzm;
    }
    public static void main(String[] args){
        Main modelLogin = new Main();
        modelLogin.login("邮箱或手机号码", "密码");
    }
}


完整工程下载地址

点击下载

有问题,欢迎评论区交流
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值