新浪微博开放平台研究-实现微博自动评论(下)

源码下载


调用新浪微博开放接口,首先要到新浪服务器进行认证,新浪微博目前采用的是OAuth2.0认证,google了一下OAuth2.0认证过程大概如下:

1.待着你的应用app key去新浪服务器,新浪收到后会返回认证页面;

2.当用户授权给你的应用后,服务器 会返回一个code给你;

3.待着你的app key、app secret和服务器返回的code再去新浪服务器,服务器会返回一个access_token给你。

然后访问接口的时候记得待着这个access_token就行了。

不知道讲对了没有,目前我的程序的确就是这么做的。

其实新浪提供了很多本版的sdk,本文就不研究了,直接使用Qt自带的QNetworkAccessManager发送请求和接受应答。

在网上搜了一个qt的http请求帮助类,挺好用的,源码如下:

头文件:

#ifndef HTTPCLIENT_H
#define HTTPCLIENT_H

#include 
#include 
#include 
#include 
#include 
#include 

class HttpClient : public QObject
{
    Q_OBJECT
public:
    explicit HttpClient(QObject *parent = 0);
    ~HttpClient();
    //http get请求
    QString get(QNetworkRequest& request);
    //http post请求
    QString post(QNetworkRequest& request, const QByteArray& data);
    //是否发生网络错误
    bool hasNetworkError(){ return this->m_hasNetworkError; }
    //获取网络连接错误代码
    int getNetworkErrorCode(){ return this->m_networkErrorCode; }
    //网络连接是否完成
    bool isHttpFinish(){ return this->m_isFinished; }
    //设置超时
    void setTimeOutLimit(int time);
signals:

public slots:
    //http请求完成
    void httpRequestFinished(QNetworkReply* reply);
    //请求超时处理
    void timeOutHandler();
    //网络错误处理
    void networkErrorHandler(QNetworkReply::NetworkError error);

private:
    QNetworkReply* m_pNetworkReply;
    QNetworkAccessManager *m_pNetworkMgr;
    bool m_hasNetworkError;//是否发生网络错误
    int m_networkErrorCode;//错误代码.如果发生网络错误,该值不为0
    QByteArray m_contentInByteArray;//请求到的内容
    QEventLoop* m_pEventLoop;//接受内容时保持响应
    volatile bool m_isFinished;
    QTimer* m_timer;//定时,用于超时检测
    int m_timeLimit;//用于设置超时

};

#endif // HTTPCLIENT_H
源文件:

#include "httpclient.h"
#include 
#include 

HttpClient::HttpClient(QObject *parent) :
    QObject(parent)
{
    this->m_contentInByteArray.clear();
    this->m_hasNetworkError = false;
    this->m_isFinished = false;
    this->m_networkErrorCode = QNetworkReply::NoError;
    this->m_pEventLoop = new QEventLoop(this);
    this->m_pNetworkMgr = new QNetworkAccessManager(this);
    this->m_pNetworkReply = NULL;
    this->m_timeLimit = 60*1000;
    this->m_timer = new QTimer(this);
    QObject::connect( this->m_pNetworkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(httpRequestFinished(QNetworkReply*)));
    //QObject::connect( network, SIGNAL(finished(QNetworkReply*)), this, SIGNAL(finished()));
    QObject::connect( this->m_timer, SIGNAL(timeout()), this, SLOT(timeOutHandler()));
}
HttpClient::~HttpClient()
{
    delete this->m_pEventLoop;
    this->m_pEventLoop = NULL;
    delete this->m_pNetworkMgr;
    this->m_pNetworkMgr = NULL;
    delete this->m_timer;
    this->m_timer = NULL;
}
QString HttpClient::get(QNetworkRequest &request)
{
    this->m_pNetworkReply = this->m_pNetworkMgr->get(request);
    QObject::connect(this->m_pNetworkReply, SIGNAL(error(QNetworkReply::NetworkError)),
                     this, SLOT(networkErrorHandler(QNetworkReply::NetworkError)));
    //计时器启动
    this->m_timer->start(this->m_timeLimit);
    this->m_pEventLoop->exec();
    this->m_pNetworkReply->close();
    delete this->m_pNetworkReply;
    this->m_pNetworkReply = NULL;
    if(!this->hasNetworkError())
    {
        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        return codec->toUnicode(this->m_contentInByteArray);
    }
    else
    {
        return QString::null;
    }
}
QString HttpClient::post(QNetworkRequest &request, const QByteArray &data)
{
    this->m_pNetworkReply = this->m_pNetworkMgr->post(request,data);
    QObject::connect(this->m_pNetworkReply, SIGNAL(error(QNetworkReply::NetworkError)),
                     this, SLOT(networkErrorHandler(QNetworkReply::NetworkError)));
    //计时器启动
    this->m_timer->start(this->m_timeLimit);
    this->m_pEventLoop->exec();
    this->m_pNetworkReply->close();
    delete this->m_pNetworkReply;
    this->m_pNetworkReply = NULL;
    if(!this->hasNetworkError())
    {
        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        return codec->toUnicode(this->m_contentInByteArray);
    }
    else
    {
        return QString::null;
    }
}
void HttpClient::httpRequestFinished(QNetworkReply *reply)
{
    this->m_isFinished = true;
    this->m_contentInByteArray = reply->readAll();
    this->m_timer->stop();
    this->m_pEventLoop->exit();
}
void HttpClient::timeOutHandler()
{
    this->m_hasNetworkError = true;
    this->m_networkErrorCode = QNetworkReply::TimeoutError;
    this->m_contentInByteArray = this->m_pNetworkReply->readAll();
    this->m_timer->stop();
    this->m_pEventLoop->exit();
}
void HttpClient::networkErrorHandler(QNetworkReply::NetworkError error)
{
    this->m_hasNetworkError = true;
    this->m_networkErrorCode = error;
    qDebug()<<"网络错误描述:"<m_pNetworkReply->errorString();
    qDebug()<<"网络错误代码:"<m_pNetworkReply->error();
}
void HttpClient::setTimeOutLimit(int time)
{
    this->m_timeLimit = time;
}

微博接口返回的是json格式,意味着需要json解析,Qt自带一个QScriptEngine,可以用来解析简单的json,但貌似解析不了两层以上的json,没有仔细研究,先凑合着用:

QString JsonUtil::getValueByKey(const QString &source, const QString &key)
{
    QScriptEngine engine;
    QScriptValue sc = engine.evaluate("value = " + source);
    QScriptValueIterator it(sc);
    while(it.hasNext())
    {
        it.next();
        if (it.name().compare(key) == 0)

            return it.value().toString();

    }
    return NULL;
}

用到的工具类都准备好了,下面进入正题。

首先看入口程序:

#include "mainwindow.h"
#include 
#include "oauthdialog.h"
#include 
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextCodec *encoding = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForTr(encoding);
    QTextCodec::setCodecForLocale(encoding);
    QTextCodec::setCodecForCStrings(encoding);
    MainWindow w;
    OauthDialog dlg(&w);

    if(dlg.exec()==QDialog::Accepted)
    {
        QApplication::setQuitOnLastWindowClosed(true);

        w.show();
        return a.exec();
    }
    return 0;
}

MainWindow是主窗口类,QauthDialog是授权对话框,首先在授权对话框进行登录授权等。

#include "oauthdialog.h"
#include "ui_oauthdialog.h"
#include "httpclient.h"
#include "jsonutil.h"
#include 
#include 
#include 
#include 

OauthDialog::OauthDialog(MainWindow* main) :
    main(main),
    ui(new Ui::OauthDialog)
{
    ui->setupUi(this);

    QUrl url;//登录授权地址
    url.setUrl("https://api.weibo.com/oauth2/authorize?client_id=yourid&redirect_uri=http://www.baidu.com&response_type=code");
    ui->m_webView->setUrl(url);
    //url变化信号,url发生变化判断是否是回调地址并截取code值
    QObject::connect( ui->m_webView, SIGNAL(urlChanged(QUrl)), this, SLOT(urlChgHandler(QUrl)) );

}

void OauthDialog::urlChgHandler(const QUrl& url)
{
    QString strUrl = url.toString();
    if (strUrl.contains("code="))
    {
        QStringList strList = strUrl.split("code=");
        QString code = strList.at(1);
        qDebug()<<"返回code值:"<post(request,postData);
        delete http;
        //qDebug()<<"content:"<main->setAccesstoken(accessToken);
        this->main->setUid(uid);
        this->accept();
    }
}

OauthDialog::~OauthDialog()
{
    delete ui;
}

上面代码获取到了access token,以后带着这个就可以访问其它接口了。

下面是获取登录用户的一些基本信息的接口:

void MainWindow::initAccountInfo()
{
    HttpClient *http = new HttpClient(this);
    QUrl url;
    url.setUrl("https://api.weibo.com/2/users/show.json");
    url.addQueryItem("access_token",this->getAccesstoken());
    url.addQueryItem("uid",this->getUid());
    QNetworkRequest request;
    request.setUrl(url);
    QString ret = http->get(request);
    JsonUtil json;
    this->ui->m_btn_name->setText(json.getValueByKey(ret,"screen_name"));
    this->ui->m_btn_attention->setText("关注:"+json.getValueByKey(ret,"friends_count"));
    this->ui->m_btn_funs->setText("粉丝:"+json.getValueByKey(ret,"followers_count"));
    this->ui->m_btn_weibo->setText("微博:"+json.getValueByKey(ret,"statuses_count"));
    delete http;
}

要想评论某条微博,首先要获取这个微博的id,试了一下获取指定用户的微博的api,不知道为什么返回来的是空,又试了一下获取指定用户的用户信息的接口,返回的内容正好包含用户最新的一条微博信息,正好用这个api做实验吧。

void MainWindow::getWeiboId()
{
    HttpClient *http = new HttpClient(this);
    QUrl url;
    url.setUrl("https://api.weibo.com/2/users/show.json");
    url.addQueryItem("access_token",this->getAccesstoken());
    url.addQueryItem("screen_name",this->ui->m_name->text());
    QNetworkRequest request;
    request.setUrl(url);
    QString ret = http->get(request);
    qDebug()<ui->m_text_ids->setText(id+name+description+weiboId + weiboContent);
    delete http;
}

用户信息api返回的json信息包含两层,Qt自带的json解析类貌似解析不了,上面代码用QString的split硬生生的把想要的信息分隔了出来,网上有很多c++的开源json工具,这里就不搞那么复杂了。

下面是发表评论:

void MainWindow::timerUpdate()
{
    HttpClient *http = new HttpClient(this);
    QUrl url;
    url.setUrl("https://api.weibo.com/2/comments/create.json");
    QNetworkRequest request;
    request.setUrl(url);

    QString content = this->ui->m_comment->document()->toPlainText();
    QString weiboid = this->ui->m_weiboid->text();

    QByteArray data = "access_token="+this->getAccesstoken().toAscii()+
            "&comment="+QUrl::toPercentEncoding(content.toUtf8()) +
            "&id="+weiboid.toAscii();

    http->post(request,data);
    delete http;
}

用了QTimer定时器,按照指定频率执行timerUpdate函数。

这样就可以自动发表评论了。

看一下截图:

新浪微博开放平台研究-实现微博自动评论(下)_第1张图片

新浪微博开放平台研究-实现微博自动评论(下)_第2张图片

新浪微博开放平台研究-实现微博自动评论(下)_第3张图片

注:评论频率不要太高了,小心被啊浪封杀!而且对普通用户,每小时的api调用次数也是有限制的。


你可能感兴趣的:(Qt,实战,新浪微博,开放平台,qt,自动评论)