HttpClient 模拟登陆知乎
最近做爬虫相关工作,我们平时用HttpWebRequest 比较多,每一个Url都要创建一个HttpWebRequest实例,
而且有些网站验证比较复杂,在登陆及后续抓取数据的时候,每次请求需要把上次的Cookie传递给这次请求。
记得这篇博客(http://www.cnblogs.com/dudu/archive/2013/03/05/httpclient.html)结尾,dudu总结了:
HttpClient最与众不同的地方是同一个HttpClient实例可以发出多次请求,每次请求是可以是完全不同的URL。
而一个HttpWebRequest实例对应于一个Url的一次请求。这才是HttpClient与HttpWebRequest的最大区别所在。
那么为什么不用HttpClient呢?
源码地址:https://github.com/zzhi/Spider4Net
本着学习的目的,那我就拿知乎练习一下,看看HttpClient好用否?
1,分析登陆页:https://www.zhihu.com/#signin

根据上图设置 DefaultRequestHeaders
HttpClient h = new HttpClient(
new HttpClientHandler
{
//CookieContainer = cookies,
AutomaticDecompression = DecompressionMethods.GZip //防止返回的json乱码
| DecompressionMethods.Deflate
}); h.DefaultRequestHeaders.Add("UserAgent", Configs.ChromeAgent);
h.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4");
h.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, sdch");
h.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
//1.首页
var response = await h.GetAsync(index);
string content = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
//获取隐藏的input值
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(content);
var xsdf = DocumentHelper.GetInputValue(doc, "_xsrf");//登录需要
nameValue["_xsrf"] = xsdf;
}
else
{
return null;
}
2,分析登陆页:https://www.zhihu.com/login/phone_num(我这里是手机和密码登录):

分析:除了要设置DefaultRequestHeaders,还需获取_xsrf的值<input type="hidden" name="_xsrf" value="3bc639713d3f8bb899009a7dfa37f9d2"/>,
这里还需注意:1, Content-Type: application/x-www-form-urlencoded; charset=UTF-8 该如何设置? 参考地址:http://ronaldrosiernet.azurewebsites.net/Blog/2013/12/07/posting_urlencoded_key_values_with_httpclient
2, 登录返回的JSON结果是乱码,该如何处理? 参考地址:http://stackoverflow.com/questions/9242472/retrieve-json-data-with-httpclient
//2.登陆
h.DefaultRequestHeaders.Clear();
h.DefaultRequestHeaders.Add("UserAgent", Configs.ChromeAgent);
h.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
h.DefaultRequestHeaders.Add("Origin", index);
h.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4");
h.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, sdch");
h.DefaultRequestHeaders.Add("Accept", "*/*");
//post参数
nameValue["password"] = PassWord;
nameValue["captcha_type"] = "cn";
nameValue["remember_me"] = "true";
nameValue["phone_num"] = Phone;
StringBuilder sb = new StringBuilder();
foreach (var key in nameValue.AllKeys)
{
sb.AppendFormat("{0}={1}&", key, nameValue[key]);
}
var str = sb.ToString().TrimEnd('&');
var request = new HttpRequestMessage(HttpMethod.Post, login);
var requestContent = str;
request.Content = new StringContent(requestContent, Encoding.UTF8, "application/x-www-form-urlencoded"); response = await h.SendAsync(request);
content = await response.Content.ReadAsStringAsync();
var dic = DocumentHelper.JsonToDic(content); if (dic.ContainsKey("msg"))
{
if (dic["msg"] != "登陆成功")//登录过于频繁,请稍等重试;errcode:100030
{
Console.WriteLine(dic["msg"]);
return null;
}
}
3. 登录成功后,后面就由大家随便折腾了。这里获取登陆后的首页信息吧。
//3.抓取首页
h.DefaultRequestHeaders.Clear();
h.DefaultRequestHeaders.Add("UserAgent", Configs.ChromeAgent);
h.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4");
h.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, sdch");
h.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
response = await h.GetAsync(index);
content = await response.Content.ReadAsStringAsync();
4,我也不对数据做处理了,看看结果:

上图是调试状态下的可视化工具视图。
源码地址:https://github.com/zzhi/Spider4Net, 里面也包含了用HttpWebRequest 方式登录的代码。
以上就是所有了,如果有时间给大家讲讲登录验证码的识别,但是这个略麻烦,需要根据具体网站的验证码训练一个验证码库,
复杂的无法识别的验证码就只能用打码兔了,其实也可以自己写个类似打码兔的软件,但需要有人值守,人工识别验证码。
这这么点东西,昨晚花费了3小时(9-12),今早写博客又花费了1小时。
HttpClient 模拟登陆知乎的更多相关文章
- Python 爬虫模拟登陆知乎
在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...
- python模拟登陆知乎并爬取数据
一些废话 看了一眼上一篇日志的时间 已然是5个月前的事情了 不禁感叹光阴荏苒其实就是我懒 几周前心血来潮想到用爬虫爬些东西 于是先后先重写了以前写过的求绩点代码 爬了草榴贴图,妹子图网,后来想爬婚恋网 ...
- 使用OKHttp模拟登陆知乎,兼谈OKHttp中Cookie的使用!
本文主要是想和大家探讨技术,让大家学会Cookie的使用,切勿做违法之事! 很多Android初学者在刚开始学习的时候,或多或少都想自己搞个应用出来,把自己学的十八般武艺全都用在这个APP上,其实这个 ...
- Scrapy 模拟登陆知乎--抓取热点话题
工具准备 在开始之前,请确保 scrpay 正确安装,手头有一款简洁而强大的浏览器, 若是你有使用 postman 那就更好了. Python 1 scrapy genspid ...
- python模拟登陆知乎
---恢复内容开始--- 在完成前面的阶段的任务之后,我们现在已经能够尝试着去模拟登录一些网站了.在这里我们模拟登录一下知乎做一下实验.笔者在这里总共用了三天多的时间,下面给大家分享一下笔者是怎么一步 ...
- 第十二篇 requests模拟登陆知乎
了解http常见状态码 可以通过输入错误的密码来找到登陆知乎的post:url 把Headers拉到底部,可以看到form data _xsrf是需要发送的,需要发送给服务端,否则会返回403错误,提 ...
- HTTPCLIENT 模拟登陆
第一步构建忽略https验证的httpclient public static CloseableHttpClient getHttpClient() throws Exception { SSLCo ...
- python使用requests模块模拟登陆知乎
from bs4 import BeautifulSoup import requests import time def captcha(captcha_data): with open(" ...
- httpClient模拟登陆校内某系统
package com.huowolf; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpE ...
随机推荐
- XCode 6.4 Alcatraz 安装的插件不可用
升级Xcode 6.4后插件都不可用了,解决办法: 1.在 Alcatraz中删除插件并退出Xcode: 2.重新打开Xcode 并安装: 3.退出Xcode: 4.进入Xcode,会提示如图,点击 ...
- HDU 5656 CA Loves GCD 01背包+gcd
题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5656 bc:http://bestcoder.hdu.edu.cn/contests/con ...
- Spring – 缓存注解
Spring缓存抽象概述 Spring框架自身并没有实现缓存解决方案,但是从3.1开始定义了org.springframework.cache.Cache和org.springframework.ca ...
- 把握曝光三要素(上):快门、光圈、ISO
概要: 如果你还没有掌握快门.光圈和ISO,那这篇文章或许对你有所帮助! 把照片比作水池.把进光量比作水.把快门比作关闭水龙头的速度.把光圈比作水龙头的大小.把感光度ISO比作水龙头的滤网,这就变得好 ...
- Sublime Text怎么设置文件在新标签打开?
设置Sublime Text新标签页tab打开文件.Sublime Text Files not opening a new tab?每次打开文件,Sublime Text总是把当前的tab打开的文件 ...
- Mac & how to uninstall LANDesk
Mac & how to uninstall LANDesk http://eddiejackson.net/wp/?p=9036 https://community.ivanti.com/d ...
- Spring异步事件
1.发布事件 @Data public class CustomEvent extends ApplicationEvent implements Serializable { private Boo ...
- HttpWebRequest和HttpWebResponse的应用
创建使用类HttpHelper: public class Httpparam { public string UserAgent { get; set; } public string Accept ...
- P2774 方格取数问题
题目背景 none! 题目描述 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于 ...
- 在ls /bin搜索的结果中找到以m开头的
ls /bin | grep ^m 在ls /bin搜索的结果中找到以m开头的 find [目录] [条件] [动作] find - name "dsa" name 指定名字 ty ...