码迷,mamicode.com
首页 > 其他好文 > 详细

Qt实战之开发CSDN下载助手 (3)(结束篇)

时间:2015-12-27 06:22:45      阅读:491      评论:0      收藏:0      [点我收藏+]

标签:

再次申明下,开发这款助手,主要是用来学习交流,并不是用来开发什么刷积分的软件。 好了,言归正传,这次,主要的分析下CSDN的下载,评论,验证码获取机制等等。

 

好,回到第二篇,当我们成功登陆时,CSDN会给我们返还一段“Set-Cookie"的内容。而这些,就是我们行走在CSDN的通行证。

技术分享

接下来我们看下下载协议:

  好,以我们上一篇写的登陆源码的文件为例:   http://download.csdn.net/download/wu5151/8945881    我们点击电信下载。。。。好吧。由于下载频繁,出现了验证码。先不管  我们看协议

 

[html] view plaincopy
 
  1. POST /index.php/source/do_download/8945881/wu5151/cea3aab69c895e0ad168609f00f208ef HTTP/1.1  
  2. Accept: text/html, application/xhtml+xml, */*  
  3. X-HttpWatch-RID: 58533-10022  
  4. Referer: http://download.csdn.net/download/wu5151/8945881  
  5. Accept-Language: zh-Hans-CN,zh-Hans;q=0.5  
  6. User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko  
  7. Content-Type: application/x-www-form-urlencoded  
  8. Accept-Encoding: gzip, deflate  
  9. Host: download.csdn.net  
  10. Content-Length: 174  
  11. DNT: 1  
  12. Connection: Keep-Alive  
  13. Cache-Control: no-cache  
[html] view plaincopy
 
  1. </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内容,看起来好无厘头的样子。查看源代码。搜索一下。结果明了了。

 

 

[html] view plaincopy
 
  1. <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">  
  2.                     <input name="ds" id="ds" type="hidden">  
  3.                     <input type="hidden" name="validate_code" value="" id="vdcode" />  
  4.                     <input type="hidden" name="basic[real_name]" value="" id="hidden_real_name">  
  5.                     <input type="hidden" name="basic[mobile]" value="" id="hidden_mobile">  
  6.                     <input type="hidden" name="basic[email]" value="" id="hidden_email">  
  7.                     <input type="hidden" name="basic[job]" value="" id="hidden_job">  
  8.                     <input type="hidden" name="basic[company]" value="" id="hidden_company">  
  9.                     <input type="hidden" name="basic[province]" value="" id="hidden_province">  
  10.                     <input type="hidden" name="basic[city]" value="" id="hidden_city">  
  11.                     <input type="hidden" name="basic[industry]" value="" id="hidden_industry">  
  12.                 </form>  


好了,我们只要匹配出post地址就好了。然后拿下参数,其中ds是表示下载方式,dx就是电信的意思。其他的作用不大。 到此我们就分析完了下载协议。这时,问题来了,出现验证码了怎么办?

 

查看get请求  我们发现地址是这样的    GET /index.php/rest/tools/validcode/source_ip_validate/10.6367190705743613 HTTP/1.1   当时我的直觉是10.636什么的应该是随机数。好吧。一码归一码。继续查源码。

 

[html] view plaincopy
 
  1. $("#imgValidcode").click(function(){  
  2.             $("#imgValidcode").attr("src","/index.php/rest/tools/validcode/source_ip_validate/1"+Math.random());  
  3.         });  


我们找到上诉内容。Math.random()就是获取随机数的。我们可以通过Qt下述方式实现

 

 

[cpp] view plaincopy
 
  1. QPixmap CGetIntegral::getValidateCodePix(QString ref, int style)  
  2. {  
  3.     // 获取验证码  "src","/index.php/rest/tools/validcode/source_ip_validate/1"+Math.random());  
  4.   
  5.     // 产生随机数  
  6.     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));  
  7.   
  8.     QString rand = "http://download.csdn.net/index.php/rest/tools/validcode/source_ip_validate/10.";  
  9.     for (int i =0; i< 16; ++i)  
  10.         rand.append(QString::number(qrand()%9));  
  11.   
  12.     if (style == 1) {  
  13.   
  14.         rand = "http://download.csdn.net/index.php/rest/tools/validcode/source_ip_validate";  
  15.     }  
  16.   
  17.     QNetworkAccessManager manager;  
  18.     QNetworkRequest networkRequest;  
  19.     networkRequest.setUrl(QUrl(rand));  
  20.     networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");  
  21.     networkRequest.setRawHeader(QByteArray("Referer"),ref.toLatin1());  
  22.     networkRequest.setRawHeader(QByteArray("Cookie"), m_Cookie.toLatin1());  
  23.   
  24.     QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(rand)));  
  25.   
  26.     QEventLoop loop;  
  27.     connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));  
  28.     loop.exec();  
  29.   
  30.     QByteArray str = reply->readAll();  
  31.     reply->deleteLater();  
  32.   
  33.     if (style == 1) {  
  34.   
  35.         QString tmp = reply->rawHeader("Set-Cookie");  
  36.         m_Cookie = tmp.remove(" path=/") + m_Cookie;  
  37.     }  
  38.   
  39.     QPixmap pixmap ;  
  40.     pixmap.loadFromData(str);  
  41.     return pixmap;  
  42. }  


通过qrand()来获取随机数0-9..。。。

 

 

好了,下载代码如下

 

[cpp] view plaincopy
 
  1. void CGetIntegral::simulationDownResource(const QString &postUrl, const QString &postRef)  
  2. {  
  3.     // 模拟下载资源  
  4.     QNetworkRequest networkRequest;  
  5.   
  6.     networkRequest.setUrl(QUrl(postUrl));  
  7.     networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");  
  8.     networkRequest.setRawHeader(QByteArray("Referer"),postRef.toLatin1());  
  9.     networkRequest.setRawHeader(QByteArray("Cookie"), m_Cookie.toLatin1());  
  10.   
  11.     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=";  
  12.   
  13.     QNetworkAccessManager manager;  
  14.     QNetworkReply *reply = manager.post(networkRequest, postData);  
  15.   
  16.     QEventLoop loop;  
  17.     connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));  
  18.     loop.exec();  
  19.   
  20.     QString str = reply->readAll();  
  21.     reply->deleteLater();  
  22.   
  23.     if (str.contains("show_validate_pop")) {  
  24.   
  25.         CHelp::setLog(QString("好吧,出现验证码了,您手动输入吧!!"));  
  26.   
  27.         m_PrePixmap = getValidateCodePix(postRef, 1);  
  28.   
  29.         m_pValidateDialog->setPixmap(m_PrePixmap);  
  30.   
  31.         if (1 != m_pValidateDialog->exec()) // 已固态模式打开  
  32.               return;  
  33.         m_ValidateCode = m_pValidateDialog->getValidateCode();  
  34.   
  35.         // 重新发出请求  
  36.         simulationDownResource(postUrl, postRef);  
  37.     } else {  
  38.   
  39.         // resetCode  
  40.         m_PrePixmap = getValidateCodePix(postRef);  
  41.     }  
  42. }  


当出现验证码的时候,我们弹出窗口,让用户输入就好了。验证码的显示,我们借助QPixmap::loadFromData(QByteArray);

 

 

最后说说评价。 协议内容如下 :

 

[plain] view plaincopy
 
  1. 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  
  2.   
  3. Host: download.csdn.net  
  4.   
  5. User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0  
  6.   
  7. Accept: text/javascript, application/javascript, */*  
  8.   
  9. Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3  
  10.   
  11. Accept-Encoding: gzip, deflate  
  12.   
  13. Content-Type: application/x-www-form-urlencoded  
  14.   
  15. X-Requested-With: XMLHttpRequest  
  16.   
  17. Referer: http://download.csdn.net/detail/wu5151/8945881  

 

 

嗯,其中评论内容通过unicode编码了。 id就是资源的id号。  jsonpcallback对应的系数,我们只要用个适当的数字表示就好,它有点类似我们win  sdk编程时的回调函数。 因为最后面有个t的系数,这个是时间戳,就是从1970,1,1至今所经过的毫秒数。这个我们可以借助QT的QDateTime类来实现。get地址中还有个rating参数,这是等级。我们就用4好了。项目该部分代码如下:

 

 

[cpp] view plaincopy
 
  1. void CGetIntegral::evaluateResource()  
  2. {  
  3.     if (m_EvaluateUrlList.count() == 0)  
  4.         emit stopEvaluate();  
  5.   
  6.     static int order =0;  
  7.   
  8.     CHelp::setLog(QString("正在评价资源:%1").arg(m_EvaluateUrlList.at(order)));  
  9.     // 评价内容  
  10.     QStringList evaluate;  
  11.     evaluate<<QString("%E8%B0%A2%E8%B0%A2%E6%A5%BC%E4%B8%BB~~%E5%A5%BD%E6%A3%92")<<  
  12.             QString("%e8%b0%a2%e8%b0%a2%e5%92%af%7e%7e%e8%b0%a2%e8%b0%a2v")<<  
  13.             QString("%e5%af%b9%e6%88%91%e5%b8%ae%e5%8a%a9%e5%be%88%e5%a4%a7%7e")<<  
  14.             QString("%e7%bb%88%e4%ba%8e%e6%89%be%e5%88%b0%e4%ba%86%7e")<<  
  15.             QString("%e8%b0%a2%e8%b0%a2%7e%e6%84%9f%e8%b0%a2%e5%88%86%e4%ba%ab");  
  16.     // 先获取时间戳  
  17.     QDateTime time = QDateTime::currentDateTime();  
  18.     QString Ts = QString::number(time.msecsTo(QDateTime(QDate(1970, 1, 1), QTime(0,0,0,0))));  
  19.     Ts.remove(‘-‘);  
  20.   
  21.     // 产生随机数  
  22.     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));  
  23.     // 选择其中一个评价内容  
  24.     QString id = m_EvaluateUrlList.at(order) ;  
  25.     id = id.mid(id.lastIndexOf(‘/‘)+1);  
  26.     QString url = "http://download.csdn.net/index.php/comment/post_comment?jsonpcallback=jsonp" + Ts+"&sourceid=" +id +  
  27.             "&content="+ evaluate[qrand()%4] +"&rating=4&t=" +Ts;  
  28.   
  29.     QNetworkAccessManager manager;  
  30.     QNetworkRequest networkRequest;  
  31.     networkRequest.setUrl(QUrl(url));  
  32.     networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");  
  33.     networkRequest.setRawHeader(QByteArray("Referer")," http://download.csdn.net"+m_EvaluateUrlList.at(order).toLatin1());  
  34.     networkRequest.setRawHeader(QByteArray("Cookie"), m_Cookie.toLatin1());  
  35.   
  36.     QNetworkReply *reply = manager.get(networkRequest);  
  37.   
  38.     QEventLoop loop;  
  39.     connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));  
  40.     loop.exec();  
  41.   
  42.     QByteArray str = reply->readAll();  
  43.     reply->deleteLater();  
  44.   
  45.     if (order == m_EvaluateUrlList.count()-1) {  
  46.         emit stopEvaluate();  
  47.         order = 0;  
  48.         return;  
  49.     }  
  50.   
  51.     ++order;  
  52.   
  53.     CHelp::setLog(QString("该资源评价成功:%1").arg(m_EvaluateUrlList.at(order)));  
  54.   
  55.     CHelp::setLog(QString("正在准备评价资源:%1").arg(m_EvaluateUrlList.at(order)));  
  56.   
  57. }  

 

至此我们已经说完了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)(结束篇)

标签:

原文地址:http://www.cnblogs.com/findumars/p/5079458.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!