在上一篇文章《调用网络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();
}

基于Qt的词典开发系列

  1. 词典框架设计及成品展示
  2. 本地词典的设计
  3. 開始菜单的设计
  4. 无边框窗体的缩放与拖动
  5. 无边框窗体的拖动
  6. 界面美化设计
  7. 调用网络API
  8. 用户登录及API调用的实现
  9. JSON数据解析
  10. 国际音标的显示
  11. 系统托盘的显示
  12. 调用讲述人
  13. 音频播放
  14. 自己主动补全功能
  15. HTML特殊字符及正則表達式
  16. 后序

作品下载地址(公布版):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的词典开发系列&lt;八&gt;--用户登录及API调用的实现的更多相关文章

  1. 【Qt编程】基于Qt的词典开发系列<二>--本地词典的设计

    我设计的词典不仅可以实现在线查单词,而且一个重大特色就是具有丰富的本地词典库:我默认加入了八个类型的词典,如下所示: 由于是本人是通信专业,因此加入了华为通信词典.电子工程词典,又由于我喜爱编程,也加 ...

  2. 【Qt编程】基于Qt的词典开发系列--后序

    从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点 ...

  3. 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计

    本文讲一讲界面设计,作品要面向用户,界面设计的好坏直接影响到用户的体验.现在的窗口设计基本都是扁平化的,你可以从window XP与window 8的窗口可以明显感觉出来.当然除了窗口本身的效果,窗口 ...

  4. 【Qt编程】基于Qt的词典开发系列<三>--开始菜单的设计

    这篇文章讲讲如何实现开始菜单(或者称为主菜单)的设计.什么是开始菜单呢?我们拿常用的软件来用图例说明,大多数软件的开始菜单在左下角,如下图: 1.window 7的开始菜单 2.有道词典的主菜单 3. ...

  5. 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示

    去年暑假的时候,作为学习Qt的实战,我写了一个名为<我爱查词典>的词典软件.后来由于导师项目及上课等原因,时间不足,所以该软件的部分功能欠缺,性能有待改善.这学期重新拿出来看时,又有很多东 ...

  6. 【Qt编程】基于Qt的词典开发系列<十>--国际音标的显示

    在年前的一篇文章中,我提到要学习Qt.于是在这学期看了一个月的qt.现在大致对qt有了一些了解.但是现在导师又把我调到了android应用开发平台,所以说qt的学习要搁置了.本打算这学期做一个单词查询 ...

  7. 【Qt编程】基于Qt的词典开发系列<十二>调用讲述人

    我们知道,win7系统自带有讲述人,即可以机器读出当前内容,具体可以将电脑锁定,然后点击左下角的按钮即可.之前在用Matlab写扫雷游戏的时候,也曾经调用过讲述人来进行游戏的语音提示.具体的Matla ...

  8. 【Qt编程】基于Qt的词典开发系列<十一>系统托盘的显示

    本文主要讨论Qt中的系统托盘的设置.系统托盘想必大家都不陌生,最常用的就是QQ.系统托盘以简单.小巧的形式能让人们较快的打开软件.废话不多说,下面开始具体介绍. 首先,新建一个Qt Gui项目,类型选 ...

  9. 【Qt编程】基于Qt的词典开发系列<五>--无边框窗口的拖动

    在上一篇文章中,我们讲述了如何进行无边框窗口的缩放与拖动,而在一些情况下,我们的窗口只需要进行拖动也不需要改变其大小,比如:QQ的登录窗口.本来在上一篇文章中已经讲述了如何进行窗口的拖动,但是却与窗口 ...

随机推荐

  1. You have not concluded your merge. (MERGE_HEAD exists)(转)

    Git本地有修改如何强制更新 本地有修改和提交,如何强制用远程的库更新更新.我尝试过用git pull -f,总是提示 You have not concluded your merge. (MERG ...

  2. 智联招聘的python岗位数据结巴分词(一)

    如何获取数据点击这里 下载之后的文件名为:all_results.csv 数据样式大概这样.然后下面我分析的是工作要求  也就是那边的绿框那一列. import csv import os impor ...

  3. centos6.5 挂载远程目录

    查看nfs程序是否安装: [root@crawler_mv02 ~]# rpm -qa |grep rpcbindrpcbind-0.2.0-13.el6_9.1.x86_64[root@crawle ...

  4. 搜索引擎--范例:新浪微博API获取最近的微博--statuses/public_timeline

    新浪微博平台跟新浪SAE一样,都是一个字“坑”,好了,不再吐槽,直入主题 1:直接登录新浪,添加网站,就直接添加我们在新浪SAE上创建的应用即可 2:填写信息,ICP备案信息号填写sinaapp.co ...

  5. Net Core 控制台程序使用Nlog 输出到log文件

    using CoreImportDataApp.Common; using Microsoft.Extensions.Configuration; using Microsoft.Extensions ...

  6. Vue cmd命令操作

    1.安装node(安装到电脑中,不同项目不需重复安装) 安装nodejs(如果不是在C:则需要配环境变量)2.打开cmd C:创建一个文件夹(名字不要用node) 1.进入该文件夹 2.node -v ...

  7. LaTeX需要renewcommand的地方

    发现了两篇关于\renewcommand的文章,希望大家有更好的建议,请多多指教! 文章来源:http://blog.csdn.net/loveaborn/article/details/915205 ...

  8. CvScalar

    CvScalar定义可存放1—4个数值的数值,其结构如下. typedef struct CvScalar{    double val[4];}CvScalar; ----------------- ...

  9. codeforces Round #441 A Trip For Meal【思路/模拟】

    A. Trip For Meal time limit per test 1 second memory limit per test 512 megabytes input standard inp ...

  10. The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple - J CONTINUE...?

    CONTINUE...? Time Limit: 1 Second      Memory Limit: 65536 KB      Special Judge DreamGrid has  clas ...