【Qt编程】基于Qt的词典开发系列<八>--用户登录及API调用的实现
来源:互联网 发布:dcs控制系统编程 编辑:程序博客网 时间:2024/05/13 07:51
在上一篇文章《调用网络API》中,我只讲述了如何直观的使用API接口以及调用API后返回的结果,本文则从程序实现的角度来实现API的调用,当然本程序的实现也是借助于扇贝网的API接口文档http://www.shanbay.com/help/developer/api/。
由API文档可知,要想调用其API,必须先注册。因此,我就注册了,账户名为nineheadedbird, 密码为123456。显然,我们要查词,首先必须得登录该账户。如果用浏览器,那就很简单,只需单纯的输入用户名和密码就可以了。可实际上,这一操作并不简单,只是浏览器为我们做了这一切。如果我们要通过程序来实现上述功能的话,就需要用到Qt中的get()函数了,而发送请求的内容格式就至关重要了。
查看请求格式
我们可以通过浏览器来查看请求格式:首先用谷歌浏览器(其他浏览器也可以,不过你要百度一下怎么来查看这些格式)打开扇贝网的登录界面http://www.shanbay.com/accounts/login/ ,在谷歌浏览器的设置中单击开发者选项,然后刷新一下页眉,就会出现如下的界面:
然后点击右边的第一个文件login,就会出现下面的内容:
从上图可以看出,内容分为三类:General、Response Headers、Request Headers
在General中可以看到Request Method为GET(一般还有另一种方式POST,这在Qt中都有对应的函数),Status Code为200表示正常。在Response Headers 中我们关注的是Set-Cookie中的csrftoken的值,因为这在我们登录时需要这个值。我们最关心的是Request Headers的内容,这部分就是我们请求函数中内容格式!参考上述的具体内容如下:
我们的程序可以写成如下的方式:
QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/accounts/login/")); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); http->get(request);
当我们执行上述的请求之后,服务器就会作答,作答的内容就是上面的Response Headers,而我们需要的是Set-Cookie中的csrftoken的值。在Qt中,我们将程序中finished信号与我们定义的槽关联,即每当网络应答结束时,都会发射这个信号,从而触发该槽函数的执行,来处理服务器的应答内容。在程序中,getCookie函数就是来获取csrftoken的值。
用户登录
获得csrftoken的值后,我们就需要实现登录操作了。除了上述的请求格式之外,我们还需要加入csrftoken的值、用户名以及密码。具体格式可见下述代码:
QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/accounts/login/")); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); request.setRawHeader("Origin","http//www.shanbay.com"); request.setRawHeader("Referer","http://www.shanbay.com/accounts/login/"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("Content-Type","application/x-www-form-urlencoded"); QByteArray postData; postData.append(QString("csrfmiddlewaretoken=%1&").arg(sessionid));//csrftoken的值 postData.append(QString("username=%1&password=%2&").arg(QUrl::toPercentEncoding(username).constData()).arg(password));//用户名及密码 postData.append("login=登录&continue=home&u=1&next="); request.setHeader(QNetworkRequest::ContentLengthHeader,postData.size()); httpAction=LoginAction; http->post(request,postData);
调用API
完成登录之后,就可以进行查词和添词操作了。除了上述提到的请求头格式之外,只需要遵守API规范(《调用网络API》中提到请求格式)即可。查词及添词的程序实现分别如下:
void netWork::queryWord(const QString &word)//查词操作{ QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/api/word/"+word)); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); httpAction=QueryWordAction; http->get(request);}void netWork::addWord(const QString &word)//添词操作{ if(word.isEmpty()) qDebug()<<"你的输入有误"; else { QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/api/learning/add/"+word)); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); httpAction=AddWordAction; http->get(request); }}
完整流程
至此,API调用的各个功能已经实现,下面给出程序的整体思路:首先获取csrftoken的值(每次都不同);然后利用用户名、密码及csrftoken的值来登录;接着就可以调用API了。在程序中,每当进行请求,都会在replyfinished函数中用case语句来分别处理这些请求对应的应答。注意,不要连续的进行请求,否则可能发生冲突。在程序中,为了防止冲突,我在connectNet请求后,在其应答处理函数中再进行loginShanbay的登录,然后在其应答函数中进行queryWord查词请求,然后在其对应的应答处理函数中进行addWord添词请求。其结果显示如下:
程序实现
下面我们给出具体的程序实现(qt 5版本,使用到网络类,需要加上QT += network):首先建立一个空的qt子项目,然后添加一个名为netWork的类,继承自QObject,然后再添加一个名为main的源文件,这三个文件的内容分别如下:
1、network.h文件
#ifndef NETWORK_H#define NETWORK_H#include <QObject>#include <QtNetwork/QNetworkAccessManager>#include<QtNetwork/QNetworkReply>#include<QtNetwork/QNetworkRequest>#include<QtNetwork/QNetworkCookie>#include<QtNetwork/QNetworkCookieJar>#include <QJsonDocument>#include <QJsonObject>#include <QJsonArray>#include <QJsonValue>#include<QString>#include<QDebug>#include<QList>#include<QUrl>#include<QByteArray>class netWork : public QObject //由于程序文件直接摘自整个项目文件,所以程序中有关的定义或函数没有使用,但是这个程序可以单独运行{ Q_OBJECTpublic: explicit netWork(QObject *parent = 0); // ~netWork(); enum HttpAction{NoAction,NetStudy,GetSessionidAction,LoginAction,QueryWordAction,AddWordAction,AddExampleAction,QueryWordExamplesAction}; HttpAction httpAction; QNetworkAccessManager * http; QString sessionid; QString queryword;//要查询的单词 QString nickname; QString username; QString password; bool isBusy; QString getCookie(const QString &name); void loginShanbay(); void queryWord(const QString &word); void queryExamples(QString learningid); void connectNet(QString username="nineheadedbird", QString password="123456"); void addWord(const QString &word);signals://这里的信号都没有用到 void connectSuccess(); void connectFail(); void verifySuccess(); void verifyFail(); void NetState(bool);public slots: void replyfinished(QNetworkReply*);};#endif // NETWORK_H
2、network.cpp文件
#include "network.h"#include<QList>#include<QDesktopServices>netWork::netWork(QObject *parent) : QObject(parent){ http=new QNetworkAccessManager(this); http->setCookieJar(new QNetworkCookieJar(this)); connect(http,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyfinished(QNetworkReply*)));//将finished信号与我们定义的槽关联,每当网络应答结束时,都会发射这个信号 isBusy=true;}QString netWork::getCookie(const QString &name)//用于获得SessionId{ foreach(QNetworkCookie cookie , http->cookieJar()->cookiesForUrl(QUrl("http://www.shanbay.com/"))) { if(cookie.name()==name) { qDebug()<<"csrftoken:"<<cookie.value(); return cookie.value(); } } return "";}void netWork::connectNet(QString username, QString password)//连接网络,使用默认的用户名和密码{ this->username=username; this->password=password; QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/accounts/login/")); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); httpAction=GetSessionidAction; http->get(request);}void netWork::replyfinished(QNetworkReply *reply)//每当执行网站应答结束后,就会执行该槽函数{ QVariant status_code=reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); qDebug()<<"code_state="<<status_code;//网络状态,200代表正常,302代表重定向,404:not found等等 if(status_code==QVariant::Invalid)//判断是否连接到网站,即当前设备能否上网 emit NetState(false); else emit NetState(true); switch(httpAction)//根据我们都进行了什么网络请求 { case NoAction: break; case GetSessionidAction://获取SessionId sessionid=getCookie("csrftoken"); if(!sessionid.isEmpty()) { emit connectSuccess(); qDebug()<<("已经连接扇贝网,正在验证用户名密码..."); loginShanbay(); }else { emit connectFail(); qDebug()<<("Cannot connect to the website!"); } break; case LoginAction: //进行登录操作 httpAction=NoAction; if(0==reply->readAll().size()) { QString nickname=QUrl::fromPercentEncoding(getCookie("username").toLatin1()); emit verifySuccess(); qDebug()<<"Successfully Login"<<nickname; queryWord("hello"); }else { emit verifyFail(); qDebug()<<"Failed to login!"; } break; case QueryWordAction://查词操作 qDebug()<<"----query word----"; qDebug()<<reply->readAll();//读取查词结果 addWord("hello");//添加单词到单词本 break; case AddWordAction://添词操作 qDebug()<<"---add word----"; qDebug()<<reply->readAll();//返回添加词语的learning_id break; default:break; }}void netWork::loginShanbay()//账户密码的登录操作{ QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/accounts/login/")); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); request.setRawHeader("Origin","http//www.shanbay.com"); request.setRawHeader("Referer","http://www.shanbay.com/accounts/login/"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("Content-Type","application/x-www-form-urlencoded"); QByteArray postData; postData.append(QString("csrfmiddlewaretoken=%1&").arg(sessionid)); postData.append(QString("username=%1&password=%2&").arg(QUrl::toPercentEncoding(username).constData()).arg(password)); postData.append("login=登录&continue=home&u=1&next="); request.setHeader(QNetworkRequest::ContentLengthHeader,postData.size()); httpAction=LoginAction; http->post(request,postData);}void netWork::queryWord(const QString &word)//查词操作{ QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/api/word/"+word)); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); httpAction=QueryWordAction; http->get(request);}void netWork::addWord(const QString &word)//添词操作{ if(word.isEmpty()) qDebug()<<"你的输入有误"; else { QNetworkRequest request; request.setUrl(QUrl("http://www.shanbay.com/api/learning/add/"+word)); request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3"); request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8"); request.setRawHeader("Cache-Control","max-age=0"); request.setRawHeader("Connection","keep-alive"); request.setRawHeader("Host","www.shanbay.com"); request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"); httpAction=AddWordAction; http->get(request); }}
3、main.cpp文件
#include <QApplication>#include "network.h"int main(int argc, char *argv[]){ QApplication a(argc, argv); netWork *nW = new netWork(); // nW->connectNet(); // nW->loginShanbay(); // nW->queryWord("hello"); return a.exec();}
基于Qt的词典开发系列
- 词典框架设计及成品展示
- 本地词典的设计
- 开始菜单的设计
- 无边框窗口的缩放与拖动
- 无边框窗口的拖动
- 界面美化设计
- 调用网络API
- 用户登录及API调用的实现
- JSON数据解析
- 国际音标的显示
- 系统托盘的显示
- 调用讲述人
- 音频播放
- 自动补全功能
- HTML特殊字符及正则表达式
- 后序
作品下载地址(发布版):http://download.csdn.net/detail/tengweitw/8548767
作品下载地址(绿色版):http://download.csdn.net/detail/tengweitw/8830495
源码下载地址:http://download.csdn.net/detail/tengweitw/8830503
原文:http://blog.csdn.net/tengweitw/article/details/45932429
作者:nineheadedbird
- 【Qt编程】基于Qt的词典开发系列<八>--用户登录及API调用的实现
- 【Qt编程】基于Qt的词典开发系列<七>--调用网络API
- 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示
- 【Qt编程】基于Qt的词典开发系列--后序
- 【Qt编程】基于Qt的词典开发系列<十二>调用讲述人
- 【Qt编程】基于Qt的词典开发系列<十五>html特殊字符及正则表达式
- 【Qt编程】基于Qt的词典开发系列<二>--本地词典的设计
- 【Qt编程】基于Qt的词典开发系列<十>--国际音标的显示
- 【Qt编程】基于Qt的词典开发系列<十一>系统托盘的显示
- 【Qt编程】基于Qt的词典开发系列<四>--无边框窗口的缩放与拖动
- 【Qt编程】基于Qt的词典开发系列<五>--无边框窗口的拖动
- 【Qt编程】基于Qt的词典开发系列<三>--开始菜单的设计
- 【Qt编程】基于Qt的词典开发系列<十三>音频播放
- 【Qt编程】基于Qt的词典开发系列<十四>自动补全功能
- 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计
- 【Qt编程】基于Qt的词典开发系列<九>--JSON数据解析
- 用Qt实现基于网络请求的用户登录(一)
- 用Qt实现基于网络请求的用户登录(二)
- OpenCV打开摄像头问题
- [小白学iOS编程04]UIDatePicker控件学习(键盘处理)
- php是有GD生成验证码
- 杭电ACM1303——Doubles
- UILabel属性
- 【Qt编程】基于Qt的词典开发系列<八>--用户登录及API调用的实现
- Decipher the internal structure of some webpage
- C#向Excel传输数据——CopyFromRecordset用法
- 你不知道的JavaScript(八)逻辑运算
- arm学习介绍
- 鸟哥的Linux私房菜(笔记)-文件权限与目录配置
- 从串口驱动的移植看linux2.6内核中的驱动模型
- Leetcode solution 01:206 Reverse Linked List
- Android开发秘籍学习笔记(六)