【Qt编程】基于Qt的词典开发系列<八>--用户登录及API调用的实现

简介: 在上一篇文章《调用网络API》中,我只讲述了如何直观的使用API接口以及调用API后返回的结果,本文则从程序实现的角度来实现API的调用,当然本程序的实现也是借助于扇贝网的API接口文档http://www.shanbay.com/help/developer/api/。

在上一篇文章《调用网络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_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)//连接网络,使用默认的用户名和密码
{
        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

目录
相关文章
|
3天前
|
安全 搜索推荐 数据挖掘
虾皮店铺商品API接口的开发、运用与收益
虾皮(Shopee)作为东南亚领先的电商平台,通过开放API接口为商家和开发者提供了全面的数据支持。本文详细介绍虾皮店铺商品API的开发与运用,涵盖注册认证、API文档解读、请求参数设置、签名生成、HTTP请求发送及响应解析等步骤,并提供Python代码示例。API接口广泛应用于电商导购、价格比较、商品推荐、数据分析等场景,带来提升用户体验、增加流量、提高运营效率等收益。开发者需注意API密钥安全、请求频率控制及遵守使用规则,确保接口稳定可靠。虾皮API推动了电商行业的创新与发展。
53 31
|
1天前
|
监控 搜索推荐 API
京东JD商品详情原数据API接口的开发、运用与收益
京东商品详情API接口是京东开放平台的重要组成部分,通过程序化方式向第三方提供商品详细信息,涵盖名称、价格、库存等。它促进了京东生态系统的建设,提升了数据利用效率,并推动了企业和商家的数字化转型。开发者可通过注册账号、获取密钥、调用接口并解析返回结果来使用该API。应用场景包括电商平台的价格监控、竞品分析、个性化推荐系统开发、移动应用开发及数据整合与共享等。该接口不仅为企业和开发者带来商业价值提升、用户体验优化,还助力数据资产积累,未来应用前景广阔。
18 9
|
5天前
|
存储 搜索推荐 API
拼多多根据ID取商品详情原数据API接口的开发、运用与收益
拼多多作为中国电商市场的重要参与者,通过开放平台提供了丰富的API接口,其中根据ID取商品详情原数据的API接口尤为重要。该接口允许开发者通过编程方式获取商品的详细信息,为电商数据分析、竞品分析、价格监测、商品推荐等多个领域带来了丰富的应用场景和显著的收益。
35 10
|
4天前
|
JSON 供应链 搜索推荐
淘宝APP分类API接口:开发、运用与收益全解析
淘宝APP作为国内领先的购物平台,拥有丰富的商品资源和庞大的用户群体。分类API接口是实现商品分类管理、查询及个性化推荐的关键工具。通过开发和使用该接口,商家可以构建分类树、进行商品查询与搜索、提供个性化推荐,从而提高销售额、增加商品曝光、提升用户体验并降低运营成本。此外,它还能帮助拓展业务范围,满足用户的多样化需求,推动电商业务的发展和创新。
22 5
|
8天前
|
JSON API 开发者
Lazada 商品评论列表 API 接口:开发、应用与收益
Lazada作为东南亚领先的电商平台,其商品评论数据蕴含丰富信息。通过开发和利用Lazada商品评论列表API接口,企业可深入挖掘这些数据,优化产品、营销和服务,提升客户体验和市场竞争力。该API基于HTTP协议,支持GET、POST等方法,开发者需注册获取API密钥,并选择合适的编程语言(如Python)进行开发。应用场景包括竞品分析、客户反馈处理及精准营销,帮助企业提升销售业绩、降低运营成本并增强品牌声誉。
25 2
|
6月前
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
210 1
|
5月前
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
129 0
|
4月前
Qt开发
Qt开发
|
4月前
|
开发工具 C++
qt开发技巧与三个问题点
本文介绍了三个Qt开发中的常见问题及其解决方法,并提供了一些实用的开发技巧。
103 0
|
5月前
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
230 2