最近学习QT ,决定写点博客练练手。今天本来是想练习一下用正则表达式解析网页的表格,所以就找了12306的余票动态信息(12306余票动态信息)原来以为是一个静态页面,看了之后发现数据是JSON格式的,那就先练练json解析吧!
1.找到票的数据来源。
打开12306的余票动态信息(
12306余票动态信息),在谷歌浏览器或者其他浏览器中按下F12,会出现调试窗口,选择Network选项卡,勾选上Preserver log(保存日志),然后按F5刷新页面,等待加载完成之后,挨个点击查看,很容易就可看到下图所示内容:
由图可知其获取数据的接口是:http://dynamic.12306.cn/otn/board/query 内容格式是json格式:
把上述借口获取到的数据粘贴到网站
http://json.cn/ 在线整理一下格式,同时也方便我们查看:
由图可知,我们获取的json 数据整体是一个object ,而我们要获取的数据 在dates 和values中,dates中的这几项是表头的日期信息。values中的内容就是票的具体信息:
values是一个数组 而数组中的每一项元素又是一个object ,这个object中包含五项内容,前四项是单独的键值对,最后一项values又是一个object.理清这些关系我们就可是写代码了。
2.获取数据并解析
抓取数据使用QT 自带的QNetworkAccessManager来抓取。
首先是界面的处理,界面上只有两个部件,一个QTreeWidget,用来显示最后的余票数据,一个QPushButton 用来触发抓取数据操作。
具体代码:
首先是new 一个对象,然后链接接受数据的槽finishedSlot.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pNAM = new QNetworkAccessManager(this);
QObject::connect(m_pNAM, SIGNAL(finished(QNetworkReply*)),
this, SLOT(finishedSlot(QNetworkReply*)));
}按钮点击时触发发送请求:
void MainWindow::on_get_ticket_clicked()
{
this->m_pNAM->get(QNetworkRequest(QUrl("http://dynamic.12306.cn/otn/board/query")));
this->ui->ticketsTree->clear();
}接收数据并处理:
void MainWindow::finishedSlot(QNetworkReply *reply)
{
//无错误返回
if(reply->error() == QNetworkReply::NoError)
{
QByteArray bytes = reply->readAll(); //获取字节
//解析数据并显示在treeWidget中
parseJsonData(bytes);
}
}主要的核心代码就在parseJsonData里边:
void MainWindow::parseJsonData(const QByteArray& bytes)
{
QStringList strHeaderList;
//出发地 //目的地
strHeaderList<<"\345\207\272\345\217\221\345\234\260"\
<<"\347\233\256\347\232\204\345\234\260";
this->ui->ticketsTree->setHeaderLabels(strHeaderList);
QJsonParseError error;
QJsonDocument jsonDocument = QJsonDocument::fromJson(bytes, &error);
if(error.error==QJsonParseError::NoError)
{
if(jsonDocument.isObject())
{
QVariantMap ticketsMap=jsonDocument.toVariant().toMap();
//获取返回码 不等于200 则不往下执行
int httpstatus=ticketsMap["httpstatus"].toInt();
if(httpstatus==200)
{
//得到 data object
QVariantMap ticketsDataMap=ticketsMap["data"].toMap();
//得到 data object 中的dates array
QVariantList ticketsDatesArray=ticketsDataMap["dates"].toList();
//treeWidget 添加表头
for(int i=0;i<ticketsDatesArray.size();i++)
{
strHeaderList.append(ticketsDatesArray.at(i).toString());
}
//设置表头
this->ui->ticketsTree->setHeaderLabels(strHeaderList);
this->ui->ticketsTree->setColumnWidth(0,100);
//设置表头适应内容大小
this->ui->ticketsTree-> header()->setResizeContentsPrecision( QHeaderView::ResizeToContents );
//解析数据设置表内容
QVariantList ticketsArray=ticketsDataMap["values"].toList();
int nCount=ticketsArray.size();
QString strCount=QString("\345\210\227\350\275\246\346\200\273\346\225\260 :%1").arg(nCount);
this->setWindowTitle(strCount);
for(int i=0;i<nCount;i++)
{
//values 下边的每一项又是一个object
QVariantMap ticketsMap=ticketsArray.at(i).toMap();
QTreeWidgetItem* ticketItem=new QTreeWidgetItem(this->ui->ticketsTree);
ticketItem->setText(0,ticketsMap["from_station_telecode_name"].toString());
ticketItem->setText(1,ticketsMap["to_station_telecode_name"].toString());
QVariantMap ticketsCountMap=ticketsMap["values"].toMap();
int j=2;
foreach (QVariant ticketCount, ticketsCountMap) {
ticketItem->setText(j,ticketCount.toString());
j++;
}
}
}
else
{
QString strRet=tr("Can not find tickets data!");
this->setWindowTitle(strRet);
}
}
}
else
{
//错误处理
}
}
本人的编译环境为QT5.5.1 +vs2010,由于构造QString时无法直接写中文,所以就用了一点猥琐的方法,直接写上了utf-8编码,关于这个编码的获取。新建一个QPushButton,把按钮名字改成你想要的汉字,然后点击编译(不用管能不能编译通过),完成之后去编译目录找到 ui_mainwindow.h ,找到 类似这样的代码:
pushbutton->setText(QApplication::translate("MainWindow", "\347\233\256\347\232\204\345\234\260", 0)); 那一串\xxx\xxx就是汉字对用的utf-8编码。
关于Json格式的解析,可以照上边的介绍的方法,在http://json.cn/ 这个网站的右侧点击查看那个小的减号查看对象类型(object 或者Array )点击加号展开这一项。
把相应的object转化成QVariantMap 把Array转化成QVariantList ,其他的不可折叠的项转化成QString 或者其他基础类型。
最后看个效果图:
源码链接:下载源码
转载请注明原文地址: https://ju.6miu.com/read-1299714.html