Qt实战之开发CSDN下载助手 (3)(结束篇)
再次申明下,开发这款助手,主要是用来学习交流,并不是用来开发什么刷积分的软件。 好了,言归正传,这次,主要的分析下CSDN的下载,评论,验证码获取机制等等。
好,回到第二篇,当我们成功登陆时,CSDN会给我们返还一段“Set-Cookie"的内容。而这些,就是我们行走在CSDN的通行证。
接下来我们看下下载协议:
好,以我们上一篇写的登陆源码的文件为例: http://download.csdn.net/download/wu5151/8945881 我们点击电信下载。。。。好吧。由于下载频繁,出现了验证码。先不管 我们看协议
- POST /index.php/source/do_download/8945881/wu5151/cea3aab69c895e0ad168609f00f208ef HTTP/1.1
- Accept: text/html, application/xhtml+xml, */*
- X-HttpWatch-RID: 58533-10022
- Referer: http://download.csdn.net/download/wu5151/8945881
- Accept-Language: zh-Hans-CN,zh-Hans;q=0.5
- User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
- Content-Type: application/x-www-form-urlencoded
- Accept-Encoding: gzip, deflate
- Host: download.csdn.net
- Content-Length: 174
- DNT: 1
- Connection: Keep-Alive
- Cache-Control: no-cache
- </pre><pre name="code" class="html">ds=dx&validate_code=&basic%5Breal_name%5D=&basic%5Bmobile%5D=&basic%5Bemail%5D=&basic%5Bjob%5D=&basic%5Bcompany%5D=&basic%5Bprovince%5D=&basic%5Bcity%5D=&basic%5Bindustry%5D=
这边我们发现,post地址出现了一串”奇怪“的字符串 cea3aa....ef 好郁闷, 不过根据上一篇所说,这个很有可能就是隐藏在http://download.csdn.net/download/wu5151/8945881 这个页面当中。包括Body内容,看起来好无厘头的样子。查看源代码。搜索一下。结果明了了。
- <form name="download_form" id="download_form" method="post" action="http://download.csdn.net/index.php/source/do_download/8945881/wu5151/cea3aab69c895e0ad168609f00f208ef" target="iframe_data">
- <input name="ds" id="ds" type="hidden">
- <input type="hidden" name="validate_code" value="" id="vdcode" />
- <input type="hidden" name="basic[real_name]" value="" id="hidden_real_name">
- <input type="hidden" name="basic[mobile]" value="" id="hidden_mobile">
- <input type="hidden" name="basic[email]" value="" id="hidden_email">
- <input type="hidden" name="basic[job]" value="" id="hidden_job">
- <input type="hidden" name="basic[company]" value="" id="hidden_company">
- <input type="hidden" name="basic[province]" value="" id="hidden_province">
- <input type="hidden" name="basic[city]" value="" id="hidden_city">
- <input type="hidden" name="basic[industry]" value="" id="hidden_industry">
- </form>
好了,我们只要匹配出post地址就好了。然后拿下参数,其中ds是表示下载方式,dx就是电信的意思。其他的作用不大。 到此我们就分析完了下载协议。这时,问题来了,出现验证码了怎么办?
查看get请求 我们发现地址是这样的 GET /index.php/rest/tools/validcode/source_ip_validate/10.6367190705743613 HTTP/1.1 当时我的直觉是10.636什么的应该是随机数。好吧。一码归一码。继续查源码。
- $("#imgValidcode").click(function(){
- $("#imgValidcode").attr("src","/index.php/rest/tools/validcode/source_ip_validate/1"+Math.random());
- });
我们找到上诉内容。Math.random()就是获取随机数的。我们可以通过Qt下述方式实现
- QPixmap CGetIntegral::getValidateCodePix(QString ref, int style)
- {
- // 获取验证码 "src","/index.php/rest/tools/validcode/source_ip_validate/1"+Math.random());
- // 产生随机数
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
- QString rand = "http://download.csdn.net/index.php/rest/tools/validcode/source_ip_validate/10.";
- for (int i =0; i< 16; ++i)
- rand.append(QString::number(qrand()%9));
- if (style == 1) {
- rand = "http://download.csdn.net/index.php/rest/tools/validcode/source_ip_validate";
- }
- QNetworkAccessManager manager;
- QNetworkRequest networkRequest;
- networkRequest.setUrl(QUrl(rand));
- networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
- networkRequest.setRawHeader(QByteArray("Referer"),ref.toLatin1());
- networkRequest.setRawHeader(QByteArray("Cookie"), m_Cookie.toLatin1());
- QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(rand)));
- QEventLoop loop;
- connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
- loop.exec();
- QByteArray str = reply->readAll();
- reply->deleteLater();
- if (style == 1) {
- QString tmp = reply->rawHeader("Set-Cookie");
- m_Cookie = tmp.remove(" path=/") + m_Cookie;
- }
- QPixmap pixmap ;
- pixmap.loadFromData(str);
- return pixmap;
- }
通过qrand()来获取随机数0-9..。。。
好了,下载代码如下
- void CGetIntegral::simulationDownResource(const QString &postUrl, const QString &postRef)
- {
- // 模拟下载资源
- QNetworkRequest networkRequest;
- networkRequest.setUrl(QUrl(postUrl));
- networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
- networkRequest.setRawHeader(QByteArray("Referer"),postRef.toLatin1());
- networkRequest.setRawHeader(QByteArray("Cookie"), m_Cookie.toLatin1());
- QByteArray postData = "ds=dx&validate_code=" +m_ValidateCode.toLatin1() +"&basic%5Breal_name%5D=&basic%5Bmobile%5D=&basic%5Bemail%5D=&basic%5Bjob%5D=&basic%5Bcompany%5D=&basic%5Bprovince%5D=&basic%5Bcity%5D=&basic%5Bindustry%5D=";
- QNetworkAccessManager manager;
- QNetworkReply *reply = manager.post(networkRequest, postData);
- QEventLoop loop;
- connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
- loop.exec();
- QString str = reply->readAll();
- reply->deleteLater();
- if (str.contains("show_validate_pop")) {
- CHelp::setLog(QString("好吧,出现验证码了,您手动输入吧!!"));
- m_PrePixmap = getValidateCodePix(postRef, 1);
- m_pValidateDialog->setPixmap(m_PrePixmap);
- if (1 != m_pValidateDialog->exec()) // 已固态模式打开
- return;
- m_ValidateCode = m_pValidateDialog->getValidateCode();
- // 重新发出请求
- simulationDownResource(postUrl, postRef);
- } else {
- // resetCode
- m_PrePixmap = getValidateCodePix(postRef);
- }
- }
当出现验证码的时候,我们弹出窗口,让用户输入就好了。验证码的显示,我们借助QPixmap::loadFromData(QByteArray);
最后说说评价。 协议内容如下 :
- GET /index.php/comment/post_comment?jsonpcallback=jsonp1427465152494&sourceid=8945881&content=%E5%A5%BD%E6%A3%92%EF%BC%81%EF%BC%81%EF%BC%81%EF%BC%81%EF%BC%81&rating=5&t=1427465372891 HTTP/1.1
- Host: download.csdn.net
- User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
- Accept: text/javascript, application/javascript, */*
- Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
- Accept-Encoding: gzip, deflate
- Content-Type: application/x-www-form-urlencoded
- X-Requested-With: XMLHttpRequest
- Referer: http://download.csdn.net/detail/wu5151/8945881
嗯,其中评论内容通过unicode编码了。 id就是资源的id号。 jsonpcallback对应的系数,我们只要用个适当的数字表示就好,它有点类似我们win sdk编程时的回调函数。 因为最后面有个t的系数,这个是时间戳,就是从1970,1,1至今所经过的毫秒数。这个我们可以借助QT的QDateTime类来实现。get地址中还有个rating参数,这是等级。我们就用4好了。项目该部分代码如下:
- void CGetIntegral::evaluateResource()
- {
- if (m_EvaluateUrlList.count() == 0)
- emit stopEvaluate();
- static int order =0;
- CHelp::setLog(QString("正在评价资源:%1").arg(m_EvaluateUrlList.at(order)));
- // 评价内容
- QStringList evaluate;
- evaluate<<QString("%E8%B0%A2%E8%B0%A2%E6%A5%BC%E4%B8%BB~~%E5%A5%BD%E6%A3%92")<<
- QString("%e8%b0%a2%e8%b0%a2%e5%92%af%7e%7e%e8%b0%a2%e8%b0%a2v")<<
- QString("%e5%af%b9%e6%88%91%e5%b8%ae%e5%8a%a9%e5%be%88%e5%a4%a7%7e")<<
- QString("%e7%bb%88%e4%ba%8e%e6%89%be%e5%88%b0%e4%ba%86%7e")<<
- QString("%e8%b0%a2%e8%b0%a2%7e%e6%84%9f%e8%b0%a2%e5%88%86%e4%ba%ab");
- // 先获取时间戳
- QDateTime time = QDateTime::currentDateTime();
- QString Ts = QString::number(time.msecsTo(QDateTime(QDate(1970, 1, 1), QTime(0,0,0,0))));
- Ts.remove('-');
- // 产生随机数
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
- // 选择其中一个评价内容
- QString id = m_EvaluateUrlList.at(order) ;
- id = id.mid(id.lastIndexOf('/')+1);
- QString url = "http://download.csdn.net/index.php/comment/post_comment?jsonpcallback=jsonp" + Ts+"&sourceid=" +id +
- "&content="+ evaluate[qrand()%4] +"&rating=4&t=" +Ts;
- QNetworkAccessManager manager;
- QNetworkRequest networkRequest;
- networkRequest.setUrl(QUrl(url));
- networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
- networkRequest.setRawHeader(QByteArray("Referer")," http://download.csdn.net"+m_EvaluateUrlList.at(order).toLatin1());
- networkRequest.setRawHeader(QByteArray("Cookie"), m_Cookie.toLatin1());
- QNetworkReply *reply = manager.get(networkRequest);
- QEventLoop loop;
- connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
- loop.exec();
- QByteArray str = reply->readAll();
- reply->deleteLater();
- if (order == m_EvaluateUrlList.count()-1) {
- emit stopEvaluate();
- order = 0;
- return;
- }
- ++order;
- CHelp::setLog(QString("该资源评价成功:%1").arg(m_EvaluateUrlList.at(order)));
- CHelp::setLog(QString("正在准备评价资源:%1").arg(m_EvaluateUrlList.at(order)));
- }
至此我们已经说完了CSDN的登录,下载,评价部分了。主要说了一些基本的抓包方式,协议分析,和一些基础性的概念。利用Qt的网络类来实现。配合正则表达式来获取所需要的部分。同时,我们这一部分操作是比较费时的,所以我们需要单独开一个线程来使用。关于线程开启,最简单的也最常用的就是采用moveToThread();函数, 但是这个函数有个限制,在帮助文档上说,你需要放在单独线程运行的对象不能给他指定父窗口。嗯。下一篇,我们谈谈Qt开发文件日志系统和屏幕日志系统。
具体代码请参看源码部分! 源码可能有所变动!!
好了,捧着开源精神。在此放出源码和可执行文件 。说明下,我加了下载限制: 资源分数5分。我并不是看重多少积分,我只是希望各位珍惜作者的劳动成果。在此说声谢谢。再次申明下,软件仅供大家学习与交流,不要用于其他用途。勿忘初心。
源码地址: http://download.csdn.net/detail/wu5151/8952891
可执行文件下载地址: http://download.csdn.net/detail/wu5151/8952871
http://blog.csdn.net/wu5151/article/details/47175841
Qt实战之开发CSDN下载助手 (3)(结束篇)的更多相关文章
- Qt实战之开发CSDN下载助手 (2)
现在,我们正式开工啦.这一篇主要学习下基本的抓包分析.学会协议登录CSDN并制作登陆界面. 准备工具: 一款http抓包工具. 可以是FireBug或者fiddler.这里我们用httpWatch. ...
- Qt实战之开发软件数据获取助手(eventFilter处理鼠标按下,event处理鼠标松开)
前段时间,受朋友委托,需要做一个能够获取别人软件文本框中内容的助手.当然这需要调用win api来解决问题.一开始,我想都没想,就用getWindowText()....居然没用,好郁闷.于是查msd ...
- Qt开发环境下载和安装
Qt是跨平台的图形开发库,目前由Digia全资子公司 Qt Company 独立运营,官方网址: http://www.qt.io/ 也可以访问Qt项目域名:http://qt-project.org ...
- 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示
去年暑假的时候,作为学习Qt的实战,我写了一个名为<我爱查词典>的词典软件.后来由于导师项目及上课等原因,时间不足,所以该软件的部分功能欠缺,性能有待改善.这学期重新拿出来看时,又有很多东 ...
- 《Qt 实战一二三》
简介 "我们来自Qt分享&&交流,我们来自Qt Quick分享&&交流",不管你是笑了,还是笑了,反正我们是认真的.我们就是要找寻一种Hold不住的 ...
- 【Qt编程】基于Qt的词典开发系列--后序
从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点 ...
- 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计
本文讲一讲界面设计,作品要面向用户,界面设计的好坏直接影响到用户的体验.现在的窗口设计基本都是扁平化的,你可以从window XP与window 8的窗口可以明显感觉出来.当然除了窗口本身的效果,窗口 ...
- 【Qt编程】基于Qt的词典开发系列<三>--开始菜单的设计
这篇文章讲讲如何实现开始菜单(或者称为主菜单)的设计.什么是开始菜单呢?我们拿常用的软件来用图例说明,大多数软件的开始菜单在左下角,如下图: 1.window 7的开始菜单 2.有道词典的主菜单 3. ...
- 【Qt编程】基于Qt的词典开发系列<二>--本地词典的设计
我设计的词典不仅可以实现在线查单词,而且一个重大特色就是具有丰富的本地词典库:我默认加入了八个类型的词典,如下所示: 由于是本人是通信专业,因此加入了华为通信词典.电子工程词典,又由于我喜爱编程,也加 ...
随机推荐
- windows下安装tern for vim
操作系统:windows8.1 64位 vim:gvim7.4 1.下载tern for vim,去官网直接下载,连接好像都是到github上(https://github.com/marijnh ...
- iis 配置php
1.CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上. CGI可以用任何一种语 ...
- myeclipse破解教程,对所有版本有效,完美支持32位和64位
破解软件下载地址 执行Run.bat文件,按照以下步骤进行激活: 第一步:输入任意用户名 第二步:点击Systemid... 按钮,自动生成本机器的systemid. 第三步:点菜单Tools-> ...
- IOS基础:深入理解Objective-c中@class的含义
objective-c中,当一个类使用到另一个类时,并且在类的头文件中需要创建被引用的指针时, 如下面代码: A.h文件 #import "B.h" @interface A : ...
- 一句话美化你的下拉框之jQuery.selectMM插件
之前很喜欢 jquery.Dropkick 这个老外美化框插件,但是:IE情况下如果数据多滚动条出现的时候就滚不了,作者也没修复 于是准备自己写一款(确切的说是修改一款吧!!).这款插件是在16素材网 ...
- ue中替换行
把替换的字符替换为^p 如:123,12,3,1, 在UE力把“,”替换未“^p”,就会替换为 1231231
- 一周学会Mootools 1.4中文教程:(5)Ajax
ajax在我们前台的开发中是非常重要的,所以我们单独拿出一节课来讲述,首先我们看一下mootools的ajax构成 语法: var myRequest=new Request([参数]); 参数: u ...
- Foreach & add remove elements
参考 http://stackoverflow.com/questions/11058384/how-to-delete-specific-array-elements-from-within-a-f ...
- 半模对话框 QProgressDialog
http://doc.qt.io/qt-4.8/qprogressdialog.html progressdialog 用到了qfuture http://blog.csdn.net/liang198 ...
- mysql数据库字段区分大小写的设置方法
alter table t_25_thread_info modify column thread_id varchar(8) character set utf8 collate utf8_bin;