【Qt编程】基于Qt的词典开发系列<八>--用户登录及API调用的实现
在上一篇文章《调用网络API》中,我仅仅讲述了怎样直观的使用API接口以及调用API后返回的结果,本文则从程序实现的角度来实现API的调用。当然本程序的实现也是借助于扇贝网的API接口文档http://www.shanbay.com/help/developer/api/。
由API文档可知,要想调用其API,必须先注冊。因此,我就注冊了,账户名为nineheadedbird。 密码为123456。
显然。我们要查词,首先必须得登录该账户。
假设用浏览器,那就非常easy,仅仅需单纯的输入username与password就能够了。可实际上。这一操作并不简单。仅仅是浏览器为我们做了这一切。
假设我们要通过程序来实现上述功能的话,就须要用到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);
当我们运行上述的请求之后,server就会作答。作答的内容就是上面的Response Headers,而我们须要的是Set-Cookie中的csrftoken的值。
在Qt中,我们将程序中finished信号与我们定义的槽关联,即每当网络应答结束时,都会发射这个信号。从而触发该槽函数的运行。来处理server的应答内容。在程序中。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_OBJECT
public:
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)//连接网络,使用默认的username与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();
}
- 词典框架设计及成品展示
- 本地词典的设计
- 開始菜单的设计
- 无边框窗体的缩放与拖动
- 无边框窗体的拖动
- 界面美化设计
- 调用网络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的词典开发系列<二>--本地词典的设计
我设计的词典不仅可以实现在线查单词,而且一个重大特色就是具有丰富的本地词典库:我默认加入了八个类型的词典,如下所示: 由于是本人是通信专业,因此加入了华为通信词典.电子工程词典,又由于我喜爱编程,也加 ...
- 【Qt编程】基于Qt的词典开发系列--后序
从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点 ...
- 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计
本文讲一讲界面设计,作品要面向用户,界面设计的好坏直接影响到用户的体验.现在的窗口设计基本都是扁平化的,你可以从window XP与window 8的窗口可以明显感觉出来.当然除了窗口本身的效果,窗口 ...
- 【Qt编程】基于Qt的词典开发系列<三>--开始菜单的设计
这篇文章讲讲如何实现开始菜单(或者称为主菜单)的设计.什么是开始菜单呢?我们拿常用的软件来用图例说明,大多数软件的开始菜单在左下角,如下图: 1.window 7的开始菜单 2.有道词典的主菜单 3. ...
- 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示
去年暑假的时候,作为学习Qt的实战,我写了一个名为<我爱查词典>的词典软件.后来由于导师项目及上课等原因,时间不足,所以该软件的部分功能欠缺,性能有待改善.这学期重新拿出来看时,又有很多东 ...
- 【Qt编程】基于Qt的词典开发系列<十>--国际音标的显示
在年前的一篇文章中,我提到要学习Qt.于是在这学期看了一个月的qt.现在大致对qt有了一些了解.但是现在导师又把我调到了android应用开发平台,所以说qt的学习要搁置了.本打算这学期做一个单词查询 ...
- 【Qt编程】基于Qt的词典开发系列<十二>调用讲述人
我们知道,win7系统自带有讲述人,即可以机器读出当前内容,具体可以将电脑锁定,然后点击左下角的按钮即可.之前在用Matlab写扫雷游戏的时候,也曾经调用过讲述人来进行游戏的语音提示.具体的Matla ...
- 【Qt编程】基于Qt的词典开发系列<十一>系统托盘的显示
本文主要讨论Qt中的系统托盘的设置.系统托盘想必大家都不陌生,最常用的就是QQ.系统托盘以简单.小巧的形式能让人们较快的打开软件.废话不多说,下面开始具体介绍. 首先,新建一个Qt Gui项目,类型选 ...
- 【Qt编程】基于Qt的词典开发系列<五>--无边框窗口的拖动
在上一篇文章中,我们讲述了如何进行无边框窗口的缩放与拖动,而在一些情况下,我们的窗口只需要进行拖动也不需要改变其大小,比如:QQ的登录窗口.本来在上一篇文章中已经讲述了如何进行窗口的拖动,但是却与窗口 ...
随机推荐
- 怎样简单编写一个html网页
# 转载请留言联系 一个HTML的基本结构如下: <!DOCTYPE html> <html lang="en"> <head> <met ...
- 回车和换行有什么区别?我们平时按下的Enter键是回车还是换行?
来源:http://www.52rd.com/blog/Detail_RD.Blog_imjacob_12317.html -------------------------------------- ...
- Selenium2+python自动化66-装饰器之运行失败截图【转载】
前言 对于用例失败截图,很多小伙伴都希望在用例执行失败的时候能自动截图,想法是很好的,实现起来并不是那么容易. 这里分享下我的一些思路,当然目前还没找到完美的解决方案,我的思路是用装饰器去解决,希望有 ...
- docker从零开始 存储(二)volumes 挂载
使用volumes 卷是保存Docker容器生成和使用的数据的首选机制.mount binds依赖于主机的目录结构,而卷完全由Docker管理.卷绑定安装有几个优点: 与绑定装入相比,卷更易于备份或迁 ...
- python算法:约瑟夫问题
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特後,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41 ...
- python socket 连续send,出现粘包问题
使用网上socket代码实现ssh功能,如下: server.py #服务端Linux系统下:处理命令并返回import socketimport os#声明类型,生成socket链接对象server ...
- 【转】Python unittest数据驱动工具:DDT
背景 python 的unittest 没有自带数据驱动功能. 所以如果使用unittest,同时又想使用数据驱动,那么就可以使用DDT来完成. DDT是 “Data-Driven Tests”的缩写 ...
- bisect二分查找模块使用
import bisectL = [1, 3, 3, 6, 8, 12, 15]x = 5x_insert_point = bisect.bisect_left(L, x)# 在L中查找x,x存在时返 ...
- DP重开
颓了差不多一周后,决定重开DP 这一周,怎么说,学了学trie树,学了学二叉堆,又学了学树状数组,差不多就这样,然后和cdc一番交流后发现,学这么多有用吗?noip的范围不就是提高篇向外扩展一下,现在 ...
- [xsy1515]小学生数学题
题意:求$\begin{align*}\left(\sum\limits_{i=1}^n\dfrac 1i\right)\%\ p^k\end{align*}$ 数学真是太可爱了== 直接推公式 设$ ...