摘要:本人希望能夠每天更換桌面背景耘戚,又覺得常規(guī)手動(dòng)步驟太過麻煩(從網(wǎng)上找圖片->下載至本地->打開本地路徑->右鍵設(shè)為壁紙),鑒于必應(yīng)壁紙質(zhì)量很高本涕,索性寫了一個(gè)程序自動(dòng)實(shí)現(xiàn)其全部過程。(文末附本程序完整源代碼的鏈接)
本文介紹從網(wǎng)上爬取圖片的實(shí)現(xiàn),即Qt的http網(wǎng)絡(luò)通訊的簡(jiǎn)單應(yīng)用抛丽。后半部分調(diào)用本地系統(tǒng)API設(shè)置壁紙過程在其他文章另有介紹撞秋。
****本人親測(cè)平臺(tái)包含****: Win10,Ubuntu16.04LTS
****運(yùn)行環(huán)境****:Qt5.7.0
第一次Get
通過QNetworkAccessManager類的get函數(shù)晦闰,爬下Bing主頁全部源碼至本地的一個(gè)txt文件中放祟,便于后續(xù)的分析處理。小貼士:用QNetworkRequest類的setUrl函數(shù)設(shè)定url呻右。
QNetworkAccessManager manager;//要用到connect跪妥,所以在頭文件中提前聲明此對(duì)象
void WallPaper::getWholeWebSource()
{
showStatusTips(PICTURE_DOWNLOADING);//一個(gè)用于顯示當(dāng)前狀態(tài)的函數(shù),詳見文末鏈接程序github源碼
QUrl url("http://cn.bing.com/");
QNetworkRequest request;
request.setUrl(url);
//將完成信號(hào)與我自定義的槽函數(shù)findPicUrl相連声滥,用finished信號(hào)傳遞reply信息至槽函數(shù)中
connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(findPicUrl(QNetworkReply*)));
//在連接了信號(hào)與槽之后眉撵,就可以進(jìn)行g(shù)et操作。get一旦完成落塑,會(huì)自動(dòng)觸發(fā)finished信號(hào)纽疟,從而轉(zhuǎn)至槽函數(shù)
manager.get(request);
}
bing主頁的源碼分析
一旦對(duì)應(yīng)第一步當(dāng)中的get的finished信號(hào)被觸發(fā),則轉(zhuǎn)至該槽函數(shù)findPicUrl芜赌,同時(shí)傳遞過來一個(gè)對(duì)象QNetworkReply *reply
仰挣。通過reply->readAll()
讀取get到的內(nèi)容
分析源碼,會(huì)發(fā)現(xiàn)壁紙URL并不完整缠沈,只是一個(gè)片段膘壶,尚無法通過它獲取壁紙圖片,需要自己再稍微拼接一下洲愤。因此颓芭,具體步驟為:1.通過一定的算法找到此片段;2.截取之柬赐;3.與http://cn.bing.com/拼接
void WallPaper::findPicUrl(QNetworkReply *reply)
{
disconnect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(findPicUrl(QNetworkReply*)));
if(reply->error() == QNetworkReply::NoError)
{
QByteArray webContent = reply->readAll();
QFile file("測(cè)試文件.txt");//寫成一個(gè)可閱讀的txt文檔亡问,用于程序測(cè)試
file.open(QIODevice::ReadWrite);
file.write(webContent);
file.close();
QByteArray targetUrl = "/az/hprichbg/rb/";//目標(biāo)url片段,通過它抓取到完整的壁紙網(wǎng)址
int indexStart = -1;
int indexEnd = -1;
indexStart = webContent.indexOf(targetUrl);
if(indexStart != -1)//若在獲取到的網(wǎng)頁源碼中找到了所需url肛宋,則get之
{
qDebug("找到了壁紙的url:");
webContent = webContent.mid(indexStart);//截取右側(cè)
indexEnd = webContent.indexOf("jpg");
indexEnd = indexEnd + 2;
QUrl url("http://cn.bing.com" + webContent.left(indexEnd + 1));//繼續(xù)截取并拼接
qDebug()<<url;
emit urlFound(url);//發(fā)射了一個(gè)信號(hào)
}
else
showStatusTips(URL_NOT_FOUND);//一個(gè)用于顯示當(dāng)前狀態(tài)的函數(shù)州藕,詳見文末鏈接程序github源碼
}
else
showStatusTips(NETWORK_CONNECTION_FAILED, reply->errorString());
}
上文中你發(fā)現(xiàn),由于findPicUrl函數(shù)也發(fā)射了一個(gè)信號(hào)酝陈,urlFound(url)床玻,因此在構(gòu)造函數(shù)處加一個(gè)connect
//當(dāng)最終計(jì)算出壁紙的目標(biāo)url后,則轉(zhuǎn)至downloadPic函數(shù)沉帮,正式開始下載壁紙
connect(this, SIGNAL(urlFound(QUrl)), this, SLOT(downloadPic(QUrl)));
第二次Get
當(dāng)urlFound信號(hào)發(fā)射后锈死,轉(zhuǎn)至downloadPic函數(shù)贫堰,get的用法與前文一致
void WallPaper::downloadPic(QUrl url)
{
QNetworkRequest request;
request.setUrl(url);
connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(savePic(QNetworkReply*)));
manager.get(request);//用finished信號(hào)傳遞reply
}
IO操作,保存至本地
當(dāng)返回信號(hào)finished時(shí)待牵,將bing返回的reply信息其屏,即圖片,保存至本地
void WallPaper::savePic(QNetworkReply *reply)
{
disconnect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(savePic(QNetworkReply*)));
if(reply->error() == QNetworkReply::NoError)
{
QPixmap picture;
//讀取IO信息
QByteArray picData = reply->readAll();
if(!picture.loadFromData(picData, "JPG"))//用QPixmap定義的對(duì)象picture缨该,讀取從bing網(wǎng)站傳過來的數(shù)據(jù)偎行,格式為jpg的圖片
{
showStatusTips(LOAD_FROM_DATA_FAILED, QString("%1").arg(picData.size()));
return;
}
//定義保存路徑filepath
filePath = QDir::homePath() + "/" + "Pictures/";
QDir dir;
dir.mkdir(filePath);
filePath += QDateTime::currentDateTime().toString("yyyy-MM-dd") + "_Bing_txmy.jpg";
//save函數(shù)保存至本地
if(!picture.save(filePath))
{
qDebug()<<"圖片保存失敗压彭!";
}
else
{//軟件其他操作
showStatusTips(WALLPAPER_READY);
showStatusTips(COUNT_DOWN_TO_CLOSE);
emit picSaved(filePath);
DataCenter &dc = DataCenter::getInstance();
QStringList paths = dc.getPicFilePaths();
int index = paths.indexOf(filePath);
if(index != -1)
dc.setCurrentIndex(index);
}
}
else
showStatusTips(DOWNLOAD_FAILED, reply->errorString());
}
Github源代碼:
一款簡(jiǎn)約的壁紙?jiān)O(shè)置程序 https://github.com/polarbear0330/DeskWallPaper
本人聯(lián)系方式:362036379@sjtu.edu.cn睦优,tfy.hi@163.com