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小时。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?