美文网首页Qt学习C++牛叉的demo
Qt之http通讯简单用法 /编写必应主页小爬虫,获取当日壁纸

Qt之http通讯简单用法 /编写必应主页小爬虫,获取当日壁纸

作者: polarbear0330 | 来源:发表于2017-06-13 11:06 被阅读309次

    摘要:本人希望能够每天更换桌面背景,又觉得常规手动步骤太过麻烦(从网上找图片->下载至本地->打开本地路径->右键设为壁纸),鉴于必应壁纸质量很高,索性写了一个程序自动实现其全部过程。(文末附本程序完整源代码的链接)
    本文介绍从网上爬取图片的实现,即Qt的http网络通讯的简单应用。后半部分调用本地系统API设置壁纸过程在其他文章另有介绍。

    ****本人亲测平台包含****: Win10,Ubuntu16.04LTS
    ****运行环境****:Qt5.7.0

    第一次Get

    通过QNetworkAccessManager类的get函数,爬下Bing主页全部源码至本地的一个txt文件中,便于后续的分析处理。小贴士:用QNetworkRequest类的setUrl函数设定url。

    QNetworkAccessManager manager;//要用到connect,所以在头文件中提前声明此对象
    
    
    void WallPaper::getWholeWebSource()
    {
     showStatusTips(PICTURE_DOWNLOADING);//一个用于显示当前状态的函数,详见文末链接程序github源码
     QUrl url("http://cn.bing.com/");
     QNetworkRequest request;
     request.setUrl(url);
    //将完成信号与我自定义的槽函数findPicUrl相连,用finished信号传递reply信息至槽函数中
    
     connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(findPicUrl(QNetworkReply*)));
    //在连接了信号与槽之后,就可以进行get操作。get一旦完成,会自动触发finished信号,从而转至槽函数
    
     manager.get(request);
    }
    
    

    bing主页的源码分析

    一旦对应第一步当中的get的finished信号被触发,则转至该槽函数findPicUrl,同时传递过来一个对象QNetworkReply *reply。通过reply->readAll()读取get到的内容

    分析源码,会发现壁纸URL并不完整,只是一个片段,尚无法通过它获取壁纸图片,需要自己再稍微拼接一下。因此,具体步骤为: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("测试文件.txt");//写成一个可阅读的txt文档,用于程序测试
     file.open(QIODevice::ReadWrite);
     file.write(webContent);
     file.close();
     QByteArray targetUrl = "/az/hprichbg/rb/";//目标url片段,通过它抓取到完整的壁纸网址
     int indexStart = -1;
     int indexEnd = -1;
     indexStart = webContent.indexOf(targetUrl);
     if(indexStart != -1)//若在获取到的网页源码中找到了所需url,则get之
     {
     qDebug("找到了壁纸的url:");
     webContent = webContent.mid(indexStart);//截取右侧
     indexEnd = webContent.indexOf("jpg");
     indexEnd = indexEnd + 2;
     QUrl url("http://cn.bing.com" + webContent.left(indexEnd + 1));//继续截取并拼接
     qDebug()<<url;
     emit urlFound(url);//发射了一个信号
     }
     else
     showStatusTips(URL_NOT_FOUND);//一个用于显示当前状态的函数,详见文末链接程序github源码
     }
     else
     showStatusTips(NETWORK_CONNECTION_FAILED, reply->errorString());
    }
    
    

    上文中你发现,由于findPicUrl函数也发射了一个信号,urlFound(url),因此在构造函数处加一个connect

    //当最终计算出壁纸的目标url后,则转至downloadPic函数,正式开始下载壁纸
    connect(this, SIGNAL(urlFound(QUrl)), this, SLOT(downloadPic(QUrl)));
    
    

    第二次Get

    当urlFound信号发射后,转至downloadPic函数,get的用法与前文一致

    void WallPaper::downloadPic(QUrl url)
    {
     QNetworkRequest request;
     request.setUrl(url);
     connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(savePic(QNetworkReply*)));
     manager.get(request);//用finished信号传递reply
    }
    
    

    IO操作,保存至本地

    当返回信号finished时,将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定义的对象picture,读取从bing网站传过来的数据,格式为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函数保存至本地
     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源代码
    一款简约的壁纸设置程序 https://github.com/polarbear0330/DeskWallPaper

    本人联系方式:362036379@sjtu.edu.cntfy.hi@163.com

    相关文章

      网友评论

      • 63ad0af7d390:qt自带的网络框架好啊还是专门的http框架好呢?
        polarbear0330:@孤独的大金毛 我也不清楚,不过你可以问问3楼。
        Ps: 你头像里的大金毛,眼神真的好萌
      • 阿尔法计算生:个人建议你修改为http异步方法,引入libevent,以网络异步事件来进行爬虫开发。
        polarbear0330:@阿尔法计算生 谢谢你的建议,我会仔细看看的
      • 静_谷:博主,但是这个应该只能解析静态网页的吧?请问有没有用wedkit解析网页的教程?
        polarbear0330:@静_谷 关于网页的东西我暂时还不会,抱歉回晚了
        静_谷:@MrAMS 哦,打错了是webkit /尴尬

      本文标题:Qt之http通讯简单用法 /编写必应主页小爬虫,获取当日壁纸

      本文链接:https://www.haomeiwen.com/subject/iykdqxtx.html