Bootstrap

【Qt 实现网页爬虫】

Qt实现爬取网页图片

实现原理

1.获取网页HTML
2.解析HTML得到图片链接
3.下载图片

展示效果图,如下所示:

一、获取到网页的HTML。

这里需要用到Qt网络编程常用的三个类:QNetworkAccessManagerQNetworkRequestQNetworkReply
使用上面的类需要引入network模块

QT += network  

向网页发送get请求

QNetworkRequest mTestRequest(QUrl(ui->UrlLineEdit->text()));
//进行网络请求,会返回一个回复,服务器回复结束,QnetworkReply就会释放finished信号
QNetworkReply *networkReply = mManager->get(mTestRequest);
//回复结束的时候QnetworkReply会释放readyRead信号
connect(networkReply,SIGNAL(readyRead()),this,SLOT(readFinishedSlot()),Qt::UniqueConnection);

返回的网页数据会在readFinshedSlot中处理

//sender()函数作用就是得到一个指针,这个指针是:当前槽函数所对应的信号是哪个对象发送的
QNetworkReply *reply = (QNetworkReply *) sender();
QByteArray data1 = reply->readAll();    //读取传回来的HTML数据
QString strData = QString(data1);
if(strData != "")
{
    ui->textEdit->setText("Get website page's data!");
}
reply->deleteLater();                   //记得释放内存
getPictureLinkFromHTML(strData);        //解析HTML,将图片链接存储在mDownloadList中
downloadResource(mDownloadList);        //对这些链接进行下载

strData中存放的就是get请求返回的HTML内容

二、解析HTML,获取到图片链接

getPictureLinkFromHTML这个接口通过正则表达式获取到匹配的字符串,并将其处理成可跳转的链接

qDebug()<<"-----------picture------------";
QStringList qsList;
qsList.clear();
QRegularExpression re("<img src=(?<path>\\S+?) (?<junk2>.*?)>", QRegularExpression::CaseInsensitiveOption);
//QRegularExpression globalMatch全部匹配,获取到所有符合这个规则的字符串集合
QRegularExpressionMatchIterator itor = re.globalMatch(qsContent);
while(itor.hasNext())
{
    QRegularExpressionMatch match = itor.next();
    QString junk2 = match.captured("junk2");
    QString path = match.captured("path");
    qsList<<path;
}
//处理downloadList数据
foreach (QString var, qsList) {
   QString str = var.replace("\"","");
   str = str.replace(">","");
   str = str.replace("'","");
   qDebug() << "_strData: " << str;
   mDownloadList << str;
}

QRegularExpression 可以使用正则表达式进行模式匹配
DownloadList中存放的是匹配成功的链接

三、下载图片

先简单说一下,下载图片的原理:仍然是通过get请求获取到链接的HTML数据,但这次我们并不是要对数据做解析,而是将这些数据写入文件中,并将文件重命名为.png格式,这样就实现了通过url下载图片。
OK,上代码

foreach (QString var, _list) {
       DownloadTipMessage _tips;
       iImageName++;
       //可以在resourcename这个属性中加入相对路径,从而将图片下载到指定文件夹
       _tips.resourcename = QString::number(iImageName);
       _tips.resourcename += ".png";
       _tips.urlpath = var;
       //初始化QFile对象
       _tips.file = new QFile(_tips.resourcename);
       //链接地址发送get请求
       QUrl url(_tips.urlpath);
       QNetworkRequest request(url);
       QNetworkReply *currentDownload;
       currentDownload = mManager->get(request);
       connect(currentDownload, SIGNAL(finished()),SLOT(downloadFinshined()));
       connect(currentDownload, SIGNAL(readyRead()),SLOT(downloadReadyRead()));
       connect(currentDownload,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(updateProgress(qint64,qint64)));
       mNetworkmap.insert(currentDownload,_tips);
    }

downloadReadyRead中主要实现将返回的HTML数据写入图片文件中

QNetworkReply *arg= dynamic_cast<QNetworkReply*>(sender());
if(!mNetworkmap[arg].file->open(QIODevice::WriteOnly)){
    delete mNetworkmap[arg].file;
    mNetworkmap[arg].file=NULL;
    return;
}
mNetworkmap[arg].file->write(arg->readAll());

downloadFinshed中实现文件的写入关闭以及QNetworkReply对象的释放

QNetworkReply *arg= dynamic_cast<QNetworkReply*>(sender());
mNetworkmap[arg].file->close();
arg->deleteLater();
arg = 0;

结尾

到这里为止,爬取网页图片到本地的流程已经结束了。
其中第二步,对于html的处理并不是很全面,但是不影响完整的实现流程。(后续,我会再更新对正则表达式的处理)

下载链接

;