最近一直在开发一个qt的项目,目前我有一个这样的需求,就是要网络请求一个账号的数据,必须经过上一次请求的一个数据结果当做下一个请求翻页的参数,而第一次请求的参数默认是0,因此如果要请求完所有的数据,必须不断循环,因此我决定用qt来实现,开始我的代码如下
void Scraping::getRequestWorking(QString id,QStringList list)
{
if(id !="")
{
for(int page=0;page<2;page++)
{
qDebug()<<id;
QString link = "https:xxx/id="+id+"&count=20&offset="+offset";
qDebug()<<link;
QUrl url(link);
QNetworkRequest request(url);
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkReply* reply = manager->get(request);
//存储返回的数据包响应
QByteArray *responseDataAll = new QByteArray();
// 连接QNetworkReply的finished信号到槽函数
connect(reply, &QNetworkReply::finished, this, [=]() {
//将字符转为json格式
*responseDataAll = reply->readAll();
QJsonDocument responseDocument = QJsonDocument::fromJson(*responseDataAll);
QJsonObject responseObject = responseDocument.object();
//获取翻页的offset
long long int offset_temp = responseObject.value("offset").toVariant().toLongLong();
qDebug()<<offset_temp;
offset = QString::number(offset_temp);
qDebug()<<"offset:"<<offset;
QJsonArray jsonArray = responseObject.value("data").toArray();
for(int ii=0;ii<jsonArray.size();ii++)
{
QString contentData = jsonArray.at(ii).toObject().value("content").toString();
QJsonDocument contentDocument = QJsonDocument::fromJson(contentData.toUtf8());
QJsonObject contentObject = contentDocument.object();
QString title = contentObject.value("title").toString();//标题
int readNum = contentObject.value("read_count").toInt();//阅读量
QString source = contentObject.value("source").toString();//来源
int comment_count = contentObject.value("comment_count").toInt();//评论量
int like_count = contentObject.value("like_count").toInt();//点赞量
int share_count = contentObject.value("share_count").toInt();//转发量
qint64 behot_time = contentObject.value("behot_time").toVariant().toLongLong();
//将时间戳转为年月日时分秒格式
QDateTime dataTime = QDateTime::fromSecsSinceEpoch(behot_time);
//将格式转为字符串格式
QString formatterDateTime = dataTime.toString("yyyy-MM-dd hh:mm");
qDebug()<<title;
qDebug()<<readNum;
qDebug()<<source;
qDebug()<<comment_count;
qDebug()<<like_count;
qDebug()<<share_count;
qDebug()<<behot_time;
qDebug()<<formatterDateTime;
}
// 在这里处理返回的数据
reply->deleteLater(); // 释放reply对象
});
}
}
else
{
qDebug() << "数据不为空";
}
}
注意,这里的函数getRequestWorking是一个子线程函数,在widget.cpp中已经声明了,
scrapingThread = new QThread(this);
//创建采集任务对象
Scraping *scrapy = new Scraping();
//将任务对象移动到子线程
scrapy->moveToThread(scrapingThread);
//主线程发送给采集子线程的参数
connect(this,&Widget::startScrap,scrapy,&Scraping::getRequestWorking);
//子线程将采集的数据发送给主线程处理
connect(scrapy,&Scraping::sendScrapData,this,&Widget::receiveData);
因此在子线程中循环进行网络请求通过更新this->offset值来请求新的数据好像是可行的,注意这里的offset在scraping.h中进行了声明,如下所示
因此按照我们的理解在子线程就可以不断更新这个offset来请求新的数据,发现运行后page=0,和page=1的link值一样,也就是offset一直都是0,究竟是为什么呢,发现了下,由于网络请求返回的数据巨大,在子线程中花费时间过多导致任务并发执行了,并没用按照顺序执行,因此无法更新offset的值。那么如何解决呢,我们可以通过QEventLoop事件循环来等待它执行完网络请求更新完offset后即可,完整的代码如下所示
void Scraping::getRequestWorking(QString id,QStringList list)
{
if(id !="")
{
for(int page=0;page<2;page++)
{
qDebug()<<id;
QString link = "https:xxx/id="+id+"&count=20&offset="+offset";
qDebug()<<link;
QUrl url(link);
QNetworkRequest request(url);
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkReply* reply = manager->get(request);
//存储返回的数据包响应
QByteArray *responseDataAll = new QByteArray();
// 连接QNetworkReply的finished信号到槽函数
QEventLoop *eventLoop = new QEventLoop();
connect(reply, &QNetworkReply::finished, this, [=]() {
//将字符转为json格式
*responseDataAll = reply->readAll();
QJsonDocument responseDocument = QJsonDocument::fromJson(*responseDataAll);
QJsonObject responseObject = responseDocument.object();
//获取翻页的offset
long long int offset_temp = responseObject.value("offset").toVariant().toLongLong();
qDebug()<<offset_temp;
offset = QString::number(offset_temp);
qDebug()<<"offset:"<<offset;
QJsonArray jsonArray = responseObject.value("data").toArray();
for(int ii=0;ii<jsonArray.size();ii++)
{
QString contentData = jsonArray.at(ii).toObject().value("content").toString();
QJsonDocument contentDocument = QJsonDocument::fromJson(contentData.toUtf8());
QJsonObject contentObject = contentDocument.object();
QString title = contentObject.value("title").toString();//标题
int readNum = contentObject.value("read_count").toInt();//阅读量
QString source = contentObject.value("source").toString();//来源
int comment_count = contentObject.value("comment_count").toInt();//评论量
int like_count = contentObject.value("like_count").toInt();//点赞量
int share_count = contentObject.value("share_count").toInt();//转发量
qint64 behot_time = contentObject.value("behot_time").toVariant().toLongLong();
//将时间戳转为年月日时分秒格式
QDateTime dataTime = QDateTime::fromSecsSinceEpoch(behot_time);
//将格式转为字符串格式
QString formatterDateTime = dataTime.toString("yyyy-MM-dd hh:mm");
qDebug()<<title;
qDebug()<<readNum;
qDebug()<<source;
qDebug()<<comment_count;
qDebug()<<like_count;
qDebug()<<share_count;
qDebug()<<behot_time;
qDebug()<<formatterDateTime;
}
// 在这里处理返回的数据
reply->deleteLater(); // 释放reply对象
eventLoop->quit(); // 停止事件循环
});
eventLoop->exec(); // 启动事件循环,等待请求完成
}
}
else
{
qDebug() << "数据不为空";
}
}
每次page的for循环后面设置启动事件循环,在connect最后停止事件循环即可实现效果!
点击此处登录后即可评论