前言

前几天刚刚接触了Java这边的关于HTTP的一个工具包—HttpClient , 那么就想借此机会练练手, 用这个工具进行对微博的模拟登录, 简单的获取一下微博的数据 , 但是大家可以不必执着于这个框架的学习 , 还可以选择其他的 , 就在写博客的时候发现了更多的网络框架 , 比如okHttp , Retrofit , OpenFeign , WebMagic , 可以着重考虑使用上面的框架来实现微博模拟登录 , 重点更加的熟悉http请求的运用方式
本人学识尚浅 , 有什么不对的地方烦请指出 .
本次演示模拟 , 仅仅为学习交流 ! 不得用于其他非法用途 !

一. HTTPClient

那么首先我们是先介绍一下HttpClient , 套一下百度百科的话嘿嘿
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议 .

HttpClient的首页地址: https://hc.apache.org/httpclient-legacy/

二. 基本流程

本次学习测试的对象为微博网页版(https://m.weibo.cn/)
模拟登录大概有下面这几个步骤 :

  1. 首先模拟访问首页 , 首页会带有一些cookie的信息 , 保存这些cookie
  2. 拿到首页的cookie之后 , 接下来我们移步账号密码登录页面, 不要进错了 , 输入账号密码之后 , 发送登录ajax请求 ( 这一步请求结果的应该都是让用手机号验证 , 我在登录时 , 还没遇到不验手机号的情况 )
  3. 根据上一步ajax请求中响应体中JSON数据中的跳转链接 , 跳转到指定的验证页面
  4. 访问验证链接首先会进行一次302跳转 , 这一步阻止链接跳转 , 获取该链接携带的cookie , 获取该链接的响应头(Response Header)里的 location 的值
  5. 根据location进行一次模拟跳转访问 , 这次跳转之后是验证手机号页面
  6. 访问获取手机验证码链接 , 会带着之前的cookie发送" 发短信 "的请求 , 响应体中json数据返回 " 输入验证码 " 的页面的链接 ( 这个链接没有什么作用 )
  7. 收到验证码之后 , 用验证码补全核验验证码的链接 , 带着之前的cookie访问 , 之后获取Json数据中的跳转链接
  8. 访问上一步跳转链接, 接下来将进行4次302跳转, 阻止每一次跳转并获取每次的携带的cookie
  9. 最终跳转到微博主页(https://m.weibo.cn/)

为什么不直接在首页使用手机号验证登录 ?
直接的话要用滑块拼图进行验证 , 滑块拼图验证这个需要更加深入的研究一下怎么加密的, 咱也是刚刚接触这个, 所以就选择了账号密码登录

三. 小提示

  1. 浏览器接收到302状态码的请求时, 自动根据 Response Header里的location里的链接进行跳转
  2. http请求的Header的是不区分大小写的
  3. 微博的json数据里有retcode时 , 为100000是为本次请求结果是正确的
  4. 浏览器会默认的为每次请求添加一些header , 这些header可能作为服务器的判定条件 , 如果不了解的可以移步
    HTTP headers 文档 : https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
  5. cookie中有一些参数 , 有些参数决定的cookie在浏览器中该怎么使用 , 如果不了解 , 移步
    HTTP header cookies 文档 : https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cookie
    HTTP set-Cookie 文档: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie
    HTTP cookies 文档 : https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
  6. 微博的每天大约只能发3次码 , 所以想要测试的时候脑子要清晰一点

四. 准备工作

开始写代码之前我们需要准备一下需要的东西
首先先导入一下必须的jar包 , 点击组件名字就可以跳转到maven对应的坐标主页

  • HttpClient工具包 , 一共有3个组件 , httpclient4.5.13 , httpcore4.4.14 , httpmime4.5.13
  • jackson工具包 , 一共3个组件 , jackson-core2.12.4 , jackson-databind2.12.4 , jackson-annotations2.12.4

五. 基本的方法&用法

如果你还不熟悉HttpClient , 那么可以先移步这里了解一下HttpClient基本使用方法

为了避免写代码过程中频繁的获取cookie,设置请求头

我自己根据HttpClient自己封装了一个Http执行器和cookie容器 , 在文章的最后介绍里面的方法

我们先看一下以下的信息 , 了解一下问题的起源

问题场景 :

cookie在浏览器中的保存方式

cookie的domain属性 , 现实生活中 , 在浏览器中进行登录时 , 浏览器会自动将cookie信息保存到浏览器中 , 这个保存并不是简单的保存到列表中 , 而是根据每一个网站的域名建立一个容器 , 当我们再次访问时该网站时 , 会自动把对应容器内的cookie带入到请求中 .

HttpClient没有类似浏览器的cookie储存方式

经过翻阅资料 , 我发现HttpClient储存cookie的方式是把每一次请求之后的cookie放入到CookieStore对象中 , 翻看源码 , 发现CookieStore内部是由一个TreeSet存储Cookie , CookieStore只提供了一个获取全部cookie的方法 , 显然不符合浏览器Cookie存取规则

Chrome浏览器会自动给每个请求加个一些Header

当我们在Chrome浏览器中调试网页时, 我们会发现 , 每次请求都会携带一些默认的Header , 如Accept ,
Accept-* , sec-fetch-* , sec-ch-* 等一系列与网页或者与我们的操作相关的header , 用来给后端服务器提供更多信息或者提升web安全

为了避免这些繁琐的步骤

六. 具体流程

首先新建一个Java项目 , 将准备工作中的Jar包导入到该项目中 ,

由于我的Clients执行器会自动根据访问的链接将header设置好 , 自动的在访问成功之后将cookie保存到指定域名的容器内, 接下来的流程中 , 将不会手动的写保存cookie的代码和设置header的代码

将json转化为对象和将cookie写入到本地 使用的是 Jackson工具包
ObjectMapper中的 readValue方法可以将JSON字符串解析为对象
ObjectMapper中的 writeValue方法可以将对象解析成JOSN字符串写入到本地文件

一. 模拟访问首页 , 访问登录页面

final String loginName = "12345678900";
final String password = "xxxxxxxxxx";
final String weibo = "https://m.weibo.cn/";
final String weiboPassportHost = "https://passport.weibo.cn";
final String loginURL = "https://passport.weibo.cn/sso/login";//创建执行器
final Clients clients = new Clients();//首先模拟访问首页,拿到cookie,然后发送登录请求
Request login = clients.createGet(weibo).next("POST",loginURL);//将登录用到的参数转化为请求参数格式的字符串,放入请求体, param如下
//username,password,savestate,r,ec,pagerefer,entry,wentry,loginfrom,
//client_id,code,qq,mainpageflag,hff,hfp
login.setReqParams( new LoginParam(loginName,password).toString() );//执行login,如果不成功抛出异常
if (login.execute() != 200) throw new RuntimeException("login.execute() != 200");//将返回的json转化为对象
BasicData loginData = genBasicData(login.getRespText());//判断json中retcode是否正确,50050011表示需要验证,50011002表示密码错误
if (loginData.getRetcode() != 50050011)System.out.println("loginInfo.getMsg():"+loginData.getMsg());
if (loginData.getRetcode() == 50011002)throw new RuntimeException(loginData.getMsg());//如果是需要验证则进入验证环节,获取json中的验证链接
String verifyURL = (String)loginData.getData().get("errurl");
//示例结果展示:
{"retcode": 50050011,"msg": "请完成验证","data": {"username": "12345678900","errurl": "https://passport.weibo.cn/verify/index?id=2YmRhIPz8AARDo_NnaoN07O40OLGtda8KBWxvZ2lu&showmenu=0&r=https%3A%2F%2Fm.weibo.cn%2F","errline": 727}
}

二. 跳转验证链接 , 向手机号发送短信


final String queryCaptchaURL = "https://passport.weibo.cn/signin/secondverify/ajsend?number=1&mask_mobile=";//把手机号的3到9位变成星号12345678900 --> 12********00
String hiddenPhone = StringUtil.hiddenString(loginName, 2, 9);//访问验证页面的链接,会302跳转,获取cookie , 然后发送短信
Request verify = clients.createGet(verifyURL).next(queryCaptchaURL+ hiddenPhone +"&msg_type=sms");//执行请求,如果不成功抛出异常
if (verify.execute() != 200) throw new RuntimeException("verify.execute() != 200");//将结果转化为对象然后判断请求是否成功
BasicData verifyData = genBasicData(verify.getRespText());
if (verifyData.getRetcode() != 100000)throw new RuntimeException(verifyData.getMsg());//验证手机验证码的页面链接,这个链接不用
String verifyCaptchaJumpURL = weiboPassportHost + verifyData.getData().get("url");

三. 输入手机验证码 , 发送验证请求

final String verifyCaptchaPageURL = "https://passport.weibo.cn/signin/secondverify/check";
final String verifyCaptchaURL = "https://passport.weibo.cn/signin/secondverify/ajcheck?msg_type=sms&code=https://passport.weibo.cn/signin/secondverify/ajcheck?msg_type=sms&code=";//输入验证码
Scanner in = new Scanner(System.in);
String captcha = "";
System.out.print("输入验证码: ");
//isCaptcha判断验证码输入的是否正确(6位纯数字)
while(!isCaptcha(captcha = in.next()))System.out.print("输入有误,请重新输入: ");// 验证验证码
HttpGet verifyCaptcha = clients.createGet(verifyCaptchaURL + captcha).setReferer(verifyCaptchaPageURL);
// 执行请求,如果不成功抛出异常
if (verifyCaptcha.execute() != 200) throw new RuntimeException("verifyCaptcha.execute() != 200");//将结果转化为对象然后判断请求是否成功
BasicData verifyCaptchaData = genBasicData(verifyCaptcha.getRespText());
if (verifyCaptchaData.getRetcode() != 100000)throw new RuntimeException(verifyCaptchaData.getMsg());//拿到最后的跳转链接
String endURL = (String)verifyCaptchaData.getData().get("url");

四. 进行4次302跳转 , 之后保存cookie到本地

final String filePath = "src/main/resources/";//进行4次302跳转,并保存每一次跳转的cookie,这里自动跳转收集了
clients.createGet(endURL).execute();//保存cookie信息到本地
String path = filePath + "weiboCoookies.json";
JsonUtils.writeValueAsFile(new File(path),clients.getWebCookies().toArray());

五. 查看模拟登录后的Cookie

至此模拟登录就完成了 , 我们带着最后的cookie就可以游历微博了
最后如果正常结束 , 我们大概能够得到21条cookie , cookie的数量还是挺多的

名字 域名 名字 域名
SUB .sina.com.cn SSOLoginState .weibo.com
SUBP .sina.com.cn ALC login.sina.com.cn
ALF .sina.com.cn LT login.sina.com.cn
SRF .passport.weibo.com SSOLoginState .weibo.cn
SRT .passport.weibo.com MLOGIN .weibo.cn
XSRF-TOKEN m.weibo.cn SUB .weibo.cn
FID .passport.weibo.cn _T_WM .weibo.cn
SUBP .sina.cn WEIBOCN_FROM .weibo.cn
SUB .sina.cn SUBP .weibo.cn
SUBP .weibo.com M_WEIBOCN_PARAMS .weibo.cn
SUB .weibo.com

可以看到登录之后微博所给的cookie还是挺全的 , 覆盖微博的各个根域 , 这个cookie虽然是从手机页面上获取的 , 但是cookie域仍然不影响我们在PC网页上使用他

七. 封装的HttpClient

我们看完了整个代码流程 , 可能对某些方法感到不解 , 在这里我会介绍一下其中的部分方法 , 想要看更多的方法的话 , 还是推荐下载下来看 , 代码里写的基本上都有中文的javadoc注释 , 代码可能存在bug , 毕竟是刚写的哈 , 发现了也见谅

资源的链接 :

虽然说是封装的HttpClient , 但是跟HttpClient耦合度还是比较低的 , 可以对接其他的HTTP框架 , 并且内容也比较简单 , 大家都可以尝试封装 , 在封装的过程中 , 都将会学习更多的与HTTP协议相关的知识

Request — 请求对象

我封装的地方使用都是我自己定义的Request接口 ,
个人觉得使用一个Request对象即可 , 有需要时将Request强转至对应的类型即可
创建HttpGet类继承HttpClient的HttpGet类 , 然后实现Request接口 , HttpPost也是如此

方法 描述
int status() 获取本次请求的状态码 , 初始值为0 , 执行后刷新
int execute() 执行本次请求 , 并返回状态码
String getRespText() 获取响应体的内容
Request next(String url) 默认执行自身 , 并返回一个根据URL创建的请求 适用于自身执行之后不需要获取响应体的请求调用 , 下一个请求的方法默认自身的一样
Request next(String method,String url) 指定了方法的next方法 , 同上
Request next(String method,String url,boolean executeCurrentReq) 指定方法并且指定是否执行本身 , true为执行
URL getURL() 获取请求的URL对象(是我定义的 , 非JDK的)
String getMethod() 获取请求的方法
Response getResponse() 获取请求的结果对象(自定义的)
HttpResponse getSrcResponse() 获取HttpClient的结果结果对象
void setCookie(Cookie cookie) 设置Cookie到cookie容器中
void setTempCookie(Cookie cookie) 设置一些临时的cookie ,执行的会带上这些cookie , 优先级大于在cookie容器中的Cookie
Collection<Cookie> getTempCookies() 获取设置的临时的Cookie
Request setReqParams(String reqParams) 设置请求参数
String getReqParams() 获取设置的请求参数
Request setReferer(String url) 设置referer , 之后会根据referer重新设置一些header
Request setReferer(URL url) 同上
Request setIgnoreCookies(String… name) 设置本次请求中不需要的携带的cookie
String[] getIgnoreCookies() 获取设置的不需要的携带的cookie
Cookie[] getResponseCookies() 获取结果的中的cookie对象 , 这些cookie对象来源于cookie容器,修改这些cookie将影响在容器中的存值
增删改Header的方法 之后是一些增删改Header的方法与HttpMessage中包含的方法一致,不在这展示了
Clients — Http请求执行器
方法 描述
HttpGet createGet(String url) 创建一个HttpGet对象 , 为其设置默认的Header
HttpGet createPost(String url) 创建一个HttpPost对象 , 为其设置默认的Header
Request createRequest(String method,String url) 创建一个Request对象 , 为其设置默认的Header
Response execute(Request req) 执行请求 , 并自动收集cookie

八. 结语

以上就是本篇文章的全部内容

**本次项目的完整源码CSDN链接 : ** https://download.csdn.net/download/m0_46344146/21712800

欢迎大家在评论区提出意见和建议 !

如果你真的从这篇文章中学到了一些新东西,喜欢它,收藏它并与你的小伙伴分享。

Java使用HttpClient模拟登录微博相关推荐

  1. JAVA使用HttpClient模拟登录正方教务系统,爬取学籍信息和课程表成绩等,超详细登录分析和代码注解

    目录 前言 分析 代码实现 第一次GET POST登录 第二次Get 第三次GET 第四次GET 第五次GET 测试 完整代码 前言 最近在做一个APP,需要获取我们学校--武汉纺织大学皇家停水断电断 ...

  2. httpclient模拟登陆微博问题

    我用httpclient模拟登陆微博报如下错误: [DEBUG] RequestAddCookies - Cookie [version: 0][name: USRHAWB][value: usrmd ...

  3. 模拟登录微博通,抓取新浪微博c#

    在前天我到公司就接到一个惊人的消息,说是新浪1.0的搜索接口关闭了,那我们的业务岂不是受很大影响,这个事太紧急了,大家在一起商讨该怎么办,跟新浪买2.0的接口肯定时间很长,最后决定抓取新浪网页的,新浪 ...

  4. HttpClient模拟登录、HtmlUnit模拟登录,jsoup爬取登录后的内容(不带验证码)

    一.HttpClient模拟登录是通过post或get请求,登录后抓取的是静态页面,动态页面使用HtmlUnit public static void main(String[] args) thro ...

  5. HttpClient 模拟登录Web版新浪微博

    上篇介绍了如何模拟登录手机版微博,过程还是比较简单的,没有设计到复杂的加密部分. 登录Web版微博的过程还是一样的,只不过这次需要提交的数据多一点. public static Cookie[] ge ...

  6. HttpClient 模拟登录手机版新浪微博

    手机版微博单点登录的URL为:http://3g.sina.com.cn/prog/wapsite/sso/login.php 我们先来看一下这个网页源代码: <html><head ...

  7. Python之模拟登录微博下载视频

    最近看到很多博主下载资源,其中有人就问:我们是搞程序出生的,能不能写段代码来实现微博下载视频资源呢? 当然,可以了,下面我使用python,来做一下演示. 1.借助JavaScript将页面滚动到最底 ...

  8. Java爬虫——人人网模拟登录

    人人网登录地址:http://www.renren.com/ 此处登录没有考虑验证码验证码. 首先对登录方法进行分析 有两种方法. 一)在Elements中分析源码 发现登录点击后的事件是http:/ ...

  9. 识别验证码模拟登录微博

    前言:在微博进行模拟登录时需要点击验证码,使用网上打码平台来对验证码进行识别,完成登录. 1.模拟登录: 首先登录微博:https://passport.weibo.cn/signin/login 我 ...

最新文章

  1. zabbix mysql路径_ZABBIX数据库迁移目录
  2. 转贴:BMP格式详解 二 (转载)
  3. Bzoj-2820 YY的GCD Mobius反演,分块
  4. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(秋季赛)- 占座位(最小割)
  5. python默认安装地址_python多版本下设置python3为默认的方法
  6. python 装饰器有哪些_python装饰器有什么用
  7. [html] 举例说明使用data-有什么优点?
  8. Hadoop的RPC工作原理
  9. 读书篇:《细说PHP》三、PHP的语言结构
  10. EEGLAB的下载与安装
  11. 安装最新版SopCast 0.4.1
  12. 远程桌面 中断计算机连接不上,中断远程桌面连接解决方案
  13. PCB多层板的一些资料
  14. IIC-LED-AW9120--1原理准备(基于麒麟座)
  15. 冒险岛V79个人用私服搭建回顾
  16. Error: [$injector:unpr] angular.js
  17. AI发展的桎梏在于理解能力?大咖开出的十一条建议「AI前沿」
  18. 神兽归笼,又是一波斗智斗勇?这款QLED电视机让你带娃更省心
  19. java se版本_补装老版本的Java SE
  20. 杂谈---一个人的两种心理

热门文章

  1. 每秒高达千万分发,如何应对直播互动平台中海量消息挑战?
  2. Hive进行身份证合法性校验
  3. Spring Boot 2.x基础教程:使用LDAP来管理用户与组织数据
  4. exe 文件打包和 cmd 常用命令
  5. Unity3D + luaframework如何做到一键打包
  6. android ExpandableTextView可伸缩的TextView
  7. flutter引入高德地图_Flutter高德地图插件
  8. 【愚公系列】2022年04月 微信小程序-地图的使用之线聚合
  9. 怎样在苹果Mac上格式化USB闪存驱动器
  10. CentOS7 linux 配置辅助DNS服务器