爬虫爬取数据的原理就是发送http请求,从返回的数据中解析出想要的数据的过程。
现在来完成一个小功能:爬取http://www.k73.com/down/3ds/list-81-1.html这个网页中的所有图片
获取网页数据:
void Dialog::getHttpData(const QString & modelUrl,QByteArray & data)
{
QUrl url = QUrl::fromUserInput(modelUrl.toUtf8());
request.setUrl(url);
QNetworkReply * reply_ = manager->get(request);
connect(reply_, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),[&](QNetworkReply::NetworkError code)
{
switch(static_cast<int>(code))
{
case QNetworkReply::ConnectionRefusedError:
qDebug() << "远程服务器拒绝连接(服务器不接受请求)";
break;
case QNetworkReply::HostNotFoundError:
qDebug() << "找不到远程主机名(无效的主机名)";
break;
case QNetworkReply::TimeoutError:
qDebug() << "与远程服务器的连接超时";
break;
default:
break;
}
});
QEventLoop eventLoop2;
connect(reply_, &QNetworkReply::finished, &eventLoop2, &QEventLoop::quit);
eventLoop2.exec(QEventLoop::ExcludeUserInputEvents);
data = reply_->readAll();
reply_->deleteLater();
}
QByteArray data得到的数据就是网页的源代码,也就是右键网页“查看源代码”出来的这些内容:
接下来就是从这些内容中解析出图片地址,用到了正则表达式
查看源代码发现这个网页的图片地址都是以 http://pic.k73.com/up/soft开头的那么正则表达式可以写成这样:
http://pic.k73.com/up/soft/.+\.(png|jpg)
以http://pic.k73.com/up/soft开头,匹配任意字符至少一次并且以.png或.jpg结尾
使用https://blog.csdn.net/kenfan1647/article/details/109429187里的工具验证这个正则表达式可以匹配到此网站的图片地址:
匹配图片地址的代码:
void Dialog::handleData(QByteArray & data)
{
QString str = QString(data);
qDebug()<<endl<<endl<<endl<<str;
QRegExp exp("http://pic.k73.com/up/soft/.+\.(png|jpg)");
exp.setMinimal(false);
QStringList list = str.split("\n");
urlList.clear();
for (int i = 0;i < list.size();++i)
{
int pos = 0;
while ((pos = exp.indexIn(list.at(i) , pos)) != -1)
{
pos += exp.matchedLength();
qDebug() << "pos :" << pos;
qDebug() << exp.cap(0);
urlList << exp.cap(0);
}
}
}
将匹配出来的图片地址保存起来
最后是下载和保存图片的代码:
void Dialog::on_btnHandle_clicked()
{
QRegExp exp("[^/]+\.(png|jpg)$");
exp.setMinimal(false);
int handleNumber = 0;
foreach (auto url, urlList)
{
int pos = 0;
QString fileName;
while ((pos = exp.indexIn(url , pos)) != -1)
{
pos += exp.matchedLength();
fileName = exp.cap(0);
}
QByteArray data;
getHttpData(url,data);
QPixmap pixmap;
pixmap.loadFromData(data);
pixmap.save(fileName);
++handleNumber;
}
}
这里希望下载图片的保存的名称用图片地址的后缀名储存,匹配图片网址后缀的正则表达式:
[^/]+\.(png|jpg)$
这个正则表达式的意思是:从后面开始匹配,匹配以.png或.jpg结尾的内容,然后向前匹配除了/之外的任意字符至少一次
验证一下:
最终结果:成功下载了网页的图片
另外注意一点,如果程序提示:qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed ,解决办法是去QtCreator的安装目录,搜索ssleay32.dll和libeay32.dll,复制到程序运行目录