QT之抓取12306余票动态信息并显示

    xiaoxiao2025-06-08  42

         最近学习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
    最新回复(0)