基于C++语言通过网络爬虫的方式获取小米笔记本的驱动信息
基于 Qt 5.12.10 以及 C++ 17 进行开发,其中借助于 dataframe-cpp 读取和存储驱动信息到文件。
首先是下载器类的实现,代码如下:
#ifndef DOWNLOADER_HPP #define DOWNLOADER_HPP #include <iostream> #include <QtNetwork> class Downloader : public QObject{ Q_OBJECT QNetworkAccessManager *manager; QNetworkReply *reply; QUrl url; QFile *file; QEventLoop * loop; public: Downloader(QString urlstr, QEventLoop * loop_ = nullptr){ url = urlstr; loop = loop_; manager = new QNetworkAccessManager(this); reply = manager->get(QNetworkRequest(url)); QFileInfo info(url.path()); QString fileName(info.fileName()); if (fileName.isEmpty()) fileName = "index.html"; file = new QFile(fileName); if(!file->open(QIODevice::WriteOnly)) { qDebug() << "file open error"; delete file; file = nullptr; return; }else qDebug() << fileName<< " is downloading ..."; connect(reply,SIGNAL(finished()),this,SLOT(finished())); connect(reply,SIGNAL(readyRead()),this,SLOT(readyRead())); } private slots: void readyRead() { if (file) file->write(reply->readAll()); //如果文件存在,则写入文件 } void finished() { file->flush(); file->close(); reply->deleteLater(); reply = nullptr; delete file; file = nullptr; if(loop != nullptr) loop->quit(); } }; #endif // DOWNLOADER_HPP
其中下面两个信号和槽的连接实现了下载中文件写入和下载完临时变量处理
connect(reply,SIGNAL(finished()),this,SLOT(finished())); connect(reply,SIGNAL(readyRead()),this,SLOT(readyRead()));
同时使用下面两句话实现根据URL自动设置文件名
QFileInfo info(url.path()); QString fileName(info.fileName());
下面讲解爬虫的核心代码,这里借助于Qt
中的QRegExp
实现HTML源代码的解析,注意本文所解析的是使用HTTP协议的网址,并且非动态加载。为了先验证源码解析的可行性,本文先从Python代码入手,Python的源码如下:
import re import os import sys import time import signal import chardet import requests import urllib.request homepage = "https://www.mi.com/service/bijiben/drivers/A29" def print_drivers_info(driver_item_dict): for type_name in driver_item_dict: print("类别:",type_name) for item_name in driver_item_dict[type_name]: print(item_name,end=" ") print("\t大小 :",driver_item_dict[type_name][item_name]["size"] ,end=" ") print("\t下载链接 :",driver_item_dict[type_name][item_name]["download_url"]) print() def get_driver_info(homepage): page= urllib.request.urlopen(homepage) #打开网页 htmlCode = page.read() #获取网页源代码 htmlCode = htmlCode.decode(chardet.detect(htmlCode)["encoding"]) #网页源代码解码 reg = r'\"main_body\":{\"section\":\[{\"body\":{\"section\":\[(.*?)\],\"sub_title\":\"适用于Windows 10操作系统\",\"title\":\"请选择驱动类型\"},\"view_type\":\"driver_info\"}\]}' reg = re.compile(reg) driver_info = reg.findall(htmlCode) reg = r'{\"items\":\[(.*?)\],\"title\":\"(.*?)\"}' reg = re.compile(reg) driver_items = reg.findall(driver_info[0]) driver_item_dict = dict() for driver_item in driver_items: type_name = driver_item[1].replace(" ","") driver_item_dict[type_name] = {} reg = r'{\"description\":\"(.*?)\",\"download_url\":\"(.*?)\",\"id\":(.*?),\"img_url\":\"(.*?)\",\"title\":\"(.*?)\"}' reg = re.compile(reg) driver_subitems = reg.findall(driver_item[0]) for driver_subitem in driver_subitems: item_name = driver_subitem[4].replace(" ","") driver_item_dict[type_name][item_name] = {} driver_item_dict[type_name][item_name]["size"] = driver_subitem[0].replace(" ","") driver_item_dict[type_name][item_name]["download_url"] = driver_subitem[1].replace(" ","") driver_item_dict[type_name][item_name]["id"] = driver_subitem[2].replace(" ","") driver_item_dict[type_name][item_name]["img_url"] = driver_subitem[3].replace(" ","") print_drivers_info(driver_item_dict) get_driver_info(homepage)
其中下面三句话是根据网站样式匹配的正则,(.*?)可以匹配所有东西,加括号代表该部分为我们需要的字符串。读者也可以根据自己的需求,设计匹配正则。
reg = r'\"main_body\":{\"section\":\[{\"body\":{\"section\":\[(.*?)\],\"sub_title\":\"适用于Windows 10操作系统\",\"title\":\"请选择驱动类型\"},\"view_type\":\"driver_info\"}\]}' reg = r'{\"items\":\[(.*?)\],\"title\":\"(.*?)\"}' reg = r'{\"description\":\"(.*?)\",\"download_url\":\"(.*?)\",\"id\":(.*?),\"img_url\":\"(.*?)\",\"title\":\"(.*?)\"}'
与之相对应的部分网页源码如下:
PageData: {"breadcrumbs":[{"action":{"path":"service","type":"url"},"id":9,"m_jump_url":"","name":"帮助中心","type":"page"},{"action":{"path":"service/bijiben","type":"url"},"id":154,"m_jump_url":"","name":"小米笔记本及周边产品","type":"url"},{"action":{"path":"service/bijiben/drivers","type":"url"},"id":155,"m_jump_url":"","name":"驱动下载","type":"page"},{"action":{"path":"service/bijiben/drivers/A29","type":"url"},"id":462,"m_jump_url":"","name":"RedmiBook Pro 15","type":"page"}],"left_tree":{"all_menu":[{"action":{"path":"service/bijiben/drivers","type":"url"},"id":155,"m_jump_url":"","name":"驱动下载","type":"page"},{"action":{"path":"service/bijiben/welcome","type":"url"},"id":160,"m_jump_url":"","name":"欢迎","type":"page"},{"action":{"path":"service/bijiben/support","type":"url"},"id":161,"m_jump_url":"","name":"常见问题","type":"page"},{"action":{"path":"service/bijiben/firstuse","type":"url"},"id":162,"m_jump_url":"","name":"首次使用","type":"page"},{"action":{"path":"service/bijiben/hardware-expansion","type":"url"},"id":163,"m_jump_url":"","name":"添加硬件与分区","type":"page"},{"action":{"path":"service/bijiben/Reset","type":"url"},"id":164,"m_jump_url":"","name":"重置系统","type":"page"},{"action":{"path":"service/bijiben/install-the-program","type":"url"},"id":165,"m_jump_url":"","name":"安装程序","type":"page"},{"action":{"path":"service/bijiben/key-function","type":"url"},"id":166,"m_jump_url":"","name":"按键功能","type":"page"},{"action":{"path":"service/bijiben/Office","type":"url"},"id":255,"m_jump_url":"","name":"Office激活与使用","type":"page"}],"fixed_menu":[{"action":{"path":"service/contact","type":"url"},"name":"联系客服"}],"parent_menu":{"action":{"path":"service/bijiben/drivers","type":"url"},"id":155,"m_jump_url":"","name":"驱动下载","type":"page"}},"m_jump_url":"","main_body":{"section":[{"body":{"section":[{"items":[{"description":"11GB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/Image/A29_Image_Recovery_20H2_V3.5.zip","id":890,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/17e339b9d687bceef9ef5cd847d4a5b0.png","title":"系统恢复"},{"description":"182MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210304/%E5%BA%94%E7%94%A8%E8%BD%AF%E4%BB%B6.zip","id":853,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/14039fc790628d99db4bfb68f9141472.png","title":"应用软件 "},{"description":"78MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210423/%E6%9C%8D%E5%8A%A1%E4%B8%AD%E5%BF%83.zip","id":872,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/783e585a1a790398091129f2aa0b0a8d.png","title":"服务中心 "},{"description":"178MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210304/MIUI%2B.zip","id":855,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/0d3af6a987aa5c5e44065f2bf8a9c73e.png","title":"MIUI+"}],"title":"系统恢复及应用"},{"items":[{"description":"54MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/WLAN_22.10.0.7.zip","id":874,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/3690a41b3c1f1b66c38e71d3c78be97e.png","title":"无线网卡 "},{"description":"515MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/IntelVGA_27.20.100.8935.zip","id":875,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/4d7f4c6aa5287edf76dc82c413180e2d.png","title":"集成显卡 "},{"description":"842MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Nvidia_27.21.14.5763.zip","id":876,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/4d7f4c6aa5287edf76dc82c413180e2d.png","title":"独立显卡 "},{"description":"611MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Audio_9075.zip","id":877,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/a413a07c62e684ce0ba94e4906815650.png","title":"声卡 "},{"description":"54MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/BT_22.10.0.2.zip","id":878,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/eb67c59b26b96c3356f15a213dda49d7.png","title":"蓝牙 "},{"description":"10MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210310/FPR_E_10301_G_230_F_11.26.1.41.zip","id":879,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/d7857b2cb2e747f45f1ea5831cb67d00.png","title":"指纹识别"},{"description":"18MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/TBT_1.41.1054.zip","id":880,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/f76b2f708de562c0430d147ae37ea178.png","title":"英特尔TBT"}],"title":"固件外设"},{"items":[{"description":"22KB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Chipset_10.1.24.5.zip","id":881,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7542212384c31a8e89e1e2c409281328.png","title":"芯片组驱动 "},{"description":"18MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/ME_2040.100.0.1029.zip","id":882,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/792018351236eaefab01bfc0f44582b0.png","title":"芯片组管理引擎 "},{"description":"2MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/SerialIO_30.100.2031.2.zip","id":883,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/a5edc351404a841677ccca4d5d426663.png","title":"芯片组串行输入输出 "},{"description":"7MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/DPTF_8.7.10401.16510.zip","id":884,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/c684bc0fd58c52cbe0569033ef55600a.png","title":"散热 "},{"description":"1KB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/power%20management.zip","id":885,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/07a8d2c1472ee16af16a579bb64208be.png","title":"电源管理优化 "},{"description":"52KB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/GNA_Driver_2.0.0.1047.zip","id":886,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/a89244a30b27abb280222f845aeac416.png","title":"英特尔GNA"}],"title":"系统性能"},{"items":[{"description":"10MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210423/OSD.zip","id":887,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/4d7f4c6aa5287edf76dc82c413180e2d.png","title":"OSD快捷键功能显示 "}],"title":"快捷键"},{"items":[{"description":"9MB","download_url":"https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/BIOS/A29/20210413/RMATG5B0P0909.zip","id":888,"img_url":"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7cf33db46a6894d211646e70b1fef4bb.png","title":"BIOS"}],"title":"BIOS"}],"sub_title":"适用于Windows 10操作系统","title":"请选择驱动类型"},"view_type":"driver_info"}]},"page_template":"4","seo":{"description":"","keywords":"","title":""}},
该代码运行后的打印信息如下:
类别: 系统恢复及应用 系统恢复 大小 : 11GB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/Image/A29_Image_Recovery_20H2_V3.5.zip 应用软件 大小 : 182MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210304/%E5%BA%94%E7%94%A8%E8%BD%AF%E4%BB%B6.zip 服务中心 大小 : 78MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210423/%E6%9C%8D%E5%8A%A1%E4%B8%AD%E5%BF%83.zip MIUI+ 大小 : 178MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210304/MIUI%2B.zip 类别: 固件外设 无线网卡 大小 : 54MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/WLAN_22.10.0.7.zip 集成显卡 大小 : 515MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/IntelVGA_27.20.100.8935.zip 独立显卡 大小 : 842MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Nvidia_27.21.14.5763.zip 声卡 大小 : 611MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Audio_9075.zip 蓝牙 大小 : 54MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/BT_22.10.0.2.zip 指纹识别 大小 : 10MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210310/FPR_E_10301_G_230_F_11.26.1.41.zip 英特尔TBT 大小 : 18MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/TBT_1.41.1054.zip 类别: 系统性能 芯片组驱动 大小 : 22KB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Chipset_10.1.24.5.zip 芯片组管理引擎 大小 : 18MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/ME_2040.100.0.1029.zip 芯片组串行输入输出 大小 : 2MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/SerialIO_30.100.2031.2.zip 散热 大小 : 7MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/DPTF_8.7.10401.16510.zip 电源管理优化 大小 : 1KB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/power%20management.zip 英特尔GNA 大小 : 52KB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/GNA_Driver_2.0.0.1047.zip 类别: 快捷键 OSD快捷键功能显示 大小 : 10MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210423/OSD.zip 类别: BIOS BIOS 大小 : 9MB 下载链接 : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/BIOS/A29/20210413/RMATG5B0P0909.zip
确定爬虫实现的可行性后,进行C++代码的设计,其实现如下:
#include <QCoreApplication> #include <QObject> #include <QtCore> #include <downloader.hpp> #include <dataframe.hpp> #include <unordered_map> #include <iostream> #include <cstdio> #include <QDateTime> QString getSpaceStr(int num, char delimeter = ' ') { QString temp; while (num--) { temp.append(delimeter); } return temp; } int main(int argc, char **argv) { QCoreApplication app(argc, argv); QFile file("URLSTR"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Please enter the correct URL of your mi computer in the file!"; } else { QByteArray line = file.readLine(); QString URLSTR = QString::fromLocal8Bit(line); if(line.size() <= 0) { qDebug() << "Please enter the correct URL of your mi computer in the file!"; } else { QUrl url(URLSTR); QNetworkAccessManager manager; QEventLoop loop; QNetworkReply *reply; qDebug() << "Reading html code from " << URLSTR; reply = manager.get(QNetworkRequest(url)); QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QString codeContent = reply->readAll(); QString str_1 = "main_body\":\\\{\"section\":\\\[\\\{\"body\":\\\{\"section\":\\\[(.*)\\\].*view_type\":\"driver_info"; QRegExp rx_1(str_1); std::unordered_map<int, std::vector<std::vector<user_variant>>> dict; std::vector<flame::dataframe < user_variant> * > type_dataframe; int max_length_name = 0; int pos_1 = 0; pos_1 = rx_1.indexIn(codeContent, pos_1); std::vector<bool> no_file = {false, false, false, false, false}; if (pos_1 >= 0) { QString str_2 = "\\\{\"items\":\\\[(.*)\\\],\"title\":\"(.*)\"\\\}"; QRegExp rx_2(str_2); rx_2.setMinimal(true); int pos_2 = 0; int type_num = 0; while (pos_2 >= 0) { pos_2 = rx_2.indexIn(rx_1.cap(1), pos_2); if (pos_2 >= 0) { ++pos_2; auto data_save = new flame::dataframe(rx_2.cap(2).toLocal8Bit().toStdString()); if (data_save->column_num() == 0) { data_save->column_paste({"name", "size", "download URL"}); if (no_file.size() > type_num) no_file[type_num] = true; else no_file.push_back(true); } type_dataframe.push_back(data_save); QString str_3 = "\\\{\"description\":\"(.*)\",\"download_url\":\"(.*)\",\"id\":(.*),\"img_url\":\"(.*)\",\"title\":\"(.*)\"\\\}"; QRegExp rx_3(str_3); rx_3.setMinimal(true); int pos_3 = 0; int row_num = 0; while (pos_3 >= 0) { pos_3 = rx_3.indexIn(rx_2.cap(1), pos_3); if (pos_3 >= 0) { ++pos_3; if (int(data_save->row_num()) - 1 < row_num) { data_save->append({rx_3.cap(5).replace(" ", "").toStdString(), rx_3.cap(1).replace(" ", "").toStdString(), rx_3.cap(2).replace(" ", "").toStdString()}); if (no_file.size() > type_num) no_file[type_num] = true; else no_file.push_back(true); } else if (std::get<std::string>((*data_save)[row_num][2]) != rx_3.cap(2).replace(" ", "").toStdString() || std::get<std::string>((*data_save)[row_num][1]) != rx_3.cap(1).replace(" ", "").toStdString() || std::get<std::string>((*data_save)[row_num][0]) != rx_3.cap(5).replace(" ", "").toStdString()) { if (dict.find(type_num) != dict.end()) { dict[type_num].emplace_back(std::vector<user_variant>{row_num, rx_3.cap(5).replace(" ", "").toStdString(), rx_3.cap(1).replace(" ", "").toStdString(), rx_3.cap(2).replace(" ", "").toStdString()}); } else { dict.insert(std::pair<int, std::vector<std::vector<user_variant>>>(type_num, { {row_num, rx_3.cap(5).replace(" ", "").toStdString(), rx_3.cap(1).replace(" ", "").toStdString(), rx_3.cap(2).replace(" ", "").toStdString()}})); } } if (max_length_name < rx_3.cap(5).replace(" ", "").toLocal8Bit().size()) max_length_name = rx_3.cap(5).replace(" ", "").toLocal8Bit().size(); row_num++; } } } type_num++; } std::cout << "Infomation of last upgrade packages of drivers : " << std::endl; for (auto items = type_dataframe.begin(); items != type_dataframe.end(); items++) { std::cout << (*items)->name() << std::endl; for (int index = 0; index < (*items)->row_num(); index++) { QString DownloadURL = QString::fromStdString(std::get<std::string>((*(*items))[index][2])); qDebug().noquote().nospace() << " |—" << QString::fromStdString(std::get<std::string>((*(*items))[index][0])) << getSpaceStr(max_length_name - QString::fromStdString( std::get<std::string>( (*(*items))[index][0])).toLocal8Bit().size()) << "\t Size : " << QString::fromStdString(std::get<std::string>((*(*items))[index][1])) << "\t Time : " << (QDateTime::fromString(*(DownloadURL.split('/').end() - 2), "yyyyMMdd").isValid() ? *( DownloadURL.split('/').end() - 2) : "xxxxxxxx") << "\t Download URL : " << DownloadURL; } std::cout << std::endl; } if (!dict.empty()) std::cout << "Available upgrade installation packages of current drivers : " << std::endl; for (auto items = dict.begin(); items != dict.end(); items++) { std::cout << type_dataframe[items->first]->name() << std::endl; for (auto item = items->second.begin(); item != items->second.end(); item++) { QString DownloadURL = QString::fromStdString(std::get<std::string>((*item)[3])); qDebug().noquote().nospace() << " |—" << QString::fromStdString(std::get<std::string>((*item)[1])) << getSpaceStr(max_length_name - QString::fromStdString( std::get<std::string>((*item)[1])).toLocal8Bit().size()) << "\t Size : " << QString::fromStdString(std::get<std::string>((*item)[2])) << "\t Time : " << (QDateTime::fromString(*(DownloadURL.split('/').end() - 2), "yyyyMMdd").isValid() ? *( DownloadURL.split('/').end() - 2) : "xxxxxxxx") << "\t Download URL : " << DownloadURL; } std::cout << std::endl; } if (!dict.empty()) { std::string answer; std::cout << "Update drivers or not [Yes/No] : "; std::cin >> answer; if (answer == "Yes") { std::cout << "Download program installation package automatically or not [Yes/No] : "; answer.clear(); std::cin >> answer; QFile *file = nullptr; bool file_ok = true; if (answer == "No") { file = new QFile("ChangeLog.TXT"); if (!file->open(QIODevice::WriteOnly | QIODevice::Text)) { std::cout << "Write into info file failed !"; file_ok = false; } } for (auto items = dict.begin(); items != dict.end(); items++) { for (auto item = items->second.begin(); item != items->second.end(); item++) { (*type_dataframe[items->first])[std::get<int>((*item)[0])] = {(*item)[1], (*item)[2], (*item)[3]}; if (answer == "Yes") { Downloader downloader(QString::fromStdString(std::get<std::string>((*item)[3])), &loop); loop.exec(); } else if (file_ok) { QTextStream out(file); QString DownloadURL = QString::fromStdString(std::get<std::string>((*item)[3])); out << QString::fromStdString(std::get<std::string>((*item)[1])) << getSpaceStr(max_length_name - QString::fromStdString( std::get<std::string>((*item)[1])).toLocal8Bit().size()) << "\t Size : " << QString::fromStdString(std::get<std::string>((*item)[2])) << "\t Time : " << (QDateTime::fromString(*(DownloadURL.split('/').end() - 2), "yyyyMMdd").isValid() ? *(DownloadURL.split('/').end() - 2) : "xxxxxxxx") << "\t Download URL : " << DownloadURL << '\n'; } type_dataframe[items->first]->to_csv(); } } if (answer == "No") { file->close(); delete file; if (file_ok) { qDebug() << "Change information has been written to ChangeLog.TXT the file, please update the drivers manually !"; } } } } else qDebug() << "No upgrade package of driver !"; type_num = 0; for (auto no_file_flag = no_file.begin(); no_file_flag != no_file.end(); no_file_flag++, type_num++) { if (*no_file_flag) { type_dataframe[type_num]->to_csv(); } } for (auto dataframe_item = type_dataframe.begin(); dataframe_item != type_dataframe.end(); dataframe_item++) delete *dataframe_item; } else qDebug() << "Information of drivers is parsed failed, please check your URL !"; } } system("pause"); return 0; }
其中下面三句是根据网站样式匹配的正则,可以看出于Python下有些许差别这是根据编码不同,接口使用方法不同导致的,但其使用方式于Python下的实现类似。
QString str_1 = "main_body\":\\\{\"section\":\\\[\\\{\"body\":\\\{\"section\":\\\[(.*)\\\].*view_type\":\"driver_info"; QString str_2 = "\\\{\"items\":\\\[(.*)\\\],\"title\":\"(.*)\"\\\}"; QString str_3 = "\\\{\"description\":\"(.*)\",\"download_url\":\"(.*)\",\"id\":(.*),\"img_url\":\"(.*)\",\"title\":\"(.*)\"\\\}";
最终该项目实现了从URLSTR
文件读取网址后获取当前最新驱动信息、上一次更新后的驱动信息以及需要更新的驱动信息,并将其打印,以及选择是否更新和自动下载,如果选择更新,将会通过dataframe
接口保存最新驱动到本地文件,如果选择自动下载,将会将安装包下载至本地,如果选择手动下载则会保存信息到ChangeLog.TXT
文件中。最终的打印信息如下:
Reading html code from "https://www.mi.com/service/bijiben/drivers/A29" Infomation of last upgrade packages of drivers : 系统恢复及应用 |—系统恢复 Size : 11GB Time : xxxxxxxx Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/Image/A29_Image_Recovery_20H2_V3.5.zip |—应用软件 Size : 182MB Time : 20210304 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210304/%E5%BA%94%E7%94%A8%E8%BD%AF%E4%BB%B6.zip |—服务中心 Size : 78MB Time : 20210423 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210423/%E6%9C%8D%E5%8A%A1%E4%B8%AD%E5%BF%83.zip |—MIUI+ Size : 178MB Time : 20210304 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210304/MIUI%2B.zip 固件外设 |—无线网卡 Size : 54MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/WLAN_22.10.0.7.zip |—集成显卡 Size : 515MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/IntelVGA_27.20.100.8935.zip |—独立显卡 Size : 842MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Nvidia_27.21.14.5763.zip |—声卡 Size : 611MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Audio_9075.zip |—蓝牙 Size : 54MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/BT_22.10.0.2.zip |—指纹识别 Size : 10MB Time : 20210310 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210310/FPR_E_10301_G_230_F_11.26.1.41.zip |—英特尔TBT Size : 18MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/TBT_1.41.1054.zip 系统性能 |—芯片组驱动 Size : 22KB Time : xxxxxxxx Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20211/Chipset_10.1.24.5.zip |—芯片组管理引擎 Size : 18MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/ME_2040.100.0.1029.zip |—芯片组串行输入输出 Size : 2MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/SerialIO_30.100.2031.2.zip |—散热 Size : 7MB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/DPTF_8.7.10401.16510.zip |—电源管理优化 Size : 1KB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-imgm/mibook-drivers/A29/20210301/power%20management.zip |—英特尔GNA Size : 52KB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/GNA_Driver_2.0.0.1047.zip 快捷键 |—OSD快捷键功能显示 Size : 10MB Time : 20210423 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A18A29/20210423/OSD.zip BIOS |—BIOS Size : 9MB Time : 20210413 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/BIOS/A29/20210413/RMATG5B0P0909.zip Available upgrade installation packages of current drivers : 系统性能 |—芯片组驱动 Size : 22KB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/Chipset_10.1.24.5.zip |—电源管理优化 Size : 1KB Time : 20210301 Download URL : https://cdn.cnbj1.fds.api.mi-img.com/mibook-drivers/A29/20210301/power%20management.zip Update drivers or not [Yes/No] : Yes Download program installation package automatically or not [Yes/No] : No Change information has been written to ChangeLog.TXT the file, please update the drivers manually !