基于QT5的网络图片爬虫

说明:

 本人没有看过爬虫相关的书籍,第一次写这种程序,这个程序只能实现简单网页图片抓取,原理很简单,没有学习过爬虫的朋友,也可做,适合学习,不适合拿去用。

程序思路大致如下:

1.下载要爬网站的页面数据,用QByteArray 对象存起来

2.处理数据,用正则表达式去扫描获得img标签下的src属性,并用容器保存属性

 QRegularExpression regExp("<img[^>]*src=['\"]([^\"']*)['\"][^>]*>");

3.遍历,下载

上运行案列:

 1. 运行起来,输入网页地址漂亮姐姐 - 高清图片,堆糖,美图壁纸兴趣社区 (duitang.com)icon-default.png?t=N7T8https://www.duitang.com/album/?id=93121087&spm=2014.12553688.202.0,点击解析图片

2.提示下载成功

3.自动保存到该项目Debug目录中

 详细介绍大致参考:

给定一个网站,自动爬取网页中的图片,下载保存到文件中

1.网络请求管理:通过QNetworkAccessManager类发起网络请求,实现了图片数据的异步下载。
2.图片下载:定义了downLoadImag函数,用于下载单张图片,并通过QImage::fromData将其转换为QImage对象。
3.错误处理:在za函数中,通过QNetworkReply::error信号捕获网络请求中的错误,并根据不同的错误类型进行处理。
4.多线程下载:在downLoadImags函数中,通过创建多个QNetworkAccessManager实例并发下载图片,提高了下载效率。
5.图片保存:在ondownLoadImags槽函数中,将下载的QImage转换为QPixmap并保存到本地文件。
6.HTML解析:在handleData函数中,使用正则表达式从HTML文本中提取图片URL,并将有效URL添加到下载列表。
7.用户界面交互:通过on_pushButton_clicked槽函数响应用户点击事件,执行图片下载和保存操作。

好了,准备工作

准备工作

1检查:

  qDebug()<<QSslSocket::supportsSsl();//是否支持ssl    
  qDebug()<<QSslSocket::sslLibraryBuildVersionString();//依赖的ssl版本

如果不支持ssl,可以通过查找资料来解决这个问题,我的话提供下面方法

  

注意一点,如果程序提示:qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed ,解决办法是去QtCreator的安装目录,搜索ssleay32.dll和libeay32.dll,复制到程序运行目录

2.依赖

 在开始之前,确保你已经安装了Qt,并且创建了一个Qt控制台应用程序项目。同时在运行程序之前,请确保已经在Qt项目的.pro文件中添加了网络访问模块的依赖

QT += network

源码:

dialog.h:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

#include"QNetworkReply"
#include"QNetworkRequest"
namespace Ui {
class Dialog;
}
class QNetworkAccessManager;
class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
private slots:
    void on_pushButton_clicked();
    void ondownLoadImags();//下载保存槽函数

private:
    QNetworkAccessManager*manager;//
    QStringList urlList;  //存储url
    QString extractedDomain; //存https或http
    bool exitMark;  //退出标志
    QList<QNetworkAccessManager*> mgrs;//manager容器
    QStringList remainUrls;//剩余的url
private:
    Ui::Dialog *ui;
    void init();
    QImage downLoadImag(const QString&modelUrl);//获取网页数据
    void za(QString &modelUrl,QByteArray &data);//处理网页源代码

    //多线程下载
    void downLoadImags(const QStringList&urlLists);

    void handleData(QByteArray&data);//处理网页源代码
    void saveImg();//保存图片
  

    void closeEvent(QCloseEvent *event);
};

#endif // DIALOG_H

dialog.cpp:

 #include "dialog.h"
#include "ui_dialog.h"
#include"QDebug"
#include <QRegularExpression>
#include"QFileInfo"
#include"QByteArrayData"
#include<QMessageBox>
#include"qnetworkaccessmanager.h"
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    init();
    qDebug()<<QSslSocket::supportsSsl();//是否支持ssl
    qDebug()<<QSslSocket::sslLibraryBuildVersionString();//依赖的ssl版本
    exitMark=false;

}

Dialog::~Dialog()
{
    delete ui;

 //   qDeleteAll(mgrs);  //系统提供的方法
}


void Dialog::closeEvent(QCloseEvent *event)
{
    QDialog::closeEvent(event);
    exitMark=true;
        foreach (QNetworkAccessManager*mgr, mgrs) {
            mgr->deleteLater();
        }
        mgrs.clear();
}

void Dialog::init()
{
    manager =new QNetworkAccessManager(this);

}
//单线程下载图片(没调用)
QImage Dialog::downLoadImag(const QString &modelUrl)
{
    QUrl url(modelUrl);//构造网址

    QNetworkRequest request;//请求

    request.setUrl(url);//设置url
    QNetworkReply * reply_ = manager->get(request);


        QEventLoop eventLoop2;
        connect(reply_, &QNetworkReply::finished, &eventLoop2, &QEventLoop::quit);
        eventLoop2.exec(QEventLoop::ExcludeUserInputEvents);

        QByteArray data = reply_->readAll();
        QImage imag=QImage::fromData(data);

        reply_->deleteLater();
        return imag;

}

//获取网站数据
void Dialog::za(QString &modelUrl, QByteArray &data)
{
    QUrl url(modelUrl);//构造网址
    QNetworkRequest request;//请求
    request.setUrl(url);//设置url
    QNetworkReply * reply_ = manager->get(request);//自动产生线程
    connect(reply_, &QNetworkReply::finished, this, [&]() {
        if (reply_->error() == QNetworkReply::NoError) {
            // 请求成功,URL是有效的

            qDebug() << "URL is valid.";
        } else {
            // 请求失败,URL可能不可用
            qDebug() << "URL is invalid or cannot be accessed.";
            QMessageBox::warning(this,"提示","请求失败,URL可能不可用");
        }
//        reply_->deleteLater();
    });
        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();

}
//多线程下载图片
void Dialog::downLoadImags(const QStringList &urlLists)
{
    foreach (const QString &url,urlLists)
    {
        if(mgrs.count()>10)//一次最多只能个图片同时下载
        {
            remainUrls<<url;
            continue;//跳过本次循环
        }
        QNetworkAccessManager *mgr =new QNetworkAccessManager();
        mgrs<<mgr;//移入
        QNetworkRequest request;
        request.setUrl(url);

        QNetworkReply * reply = mgr->get(request);//自动产生新线程
        connect(reply,&QNetworkReply::finished,this,&Dialog::ondownLoadImags);
    }
}
//保存图片槽函数
void Dialog::ondownLoadImags()
{
    QObject *obj =this->sender();   //sender方法获取replay
    QNetworkReply *reply =qobject_cast<QNetworkReply*>(obj);

    if(reply==NULL)
       return;

    QByteArray data= reply->readAll();

    QNetworkAccessManager *mgr =reply->manager();
    mgrs.removeAll(mgr);
    mgr->deleteLater();  //延后删除



    QImage imag = QImage::fromData(data);
    QFileInfo info(reply->url().toString());//  转换!!!!
    QString fileName =info.fileName();
    // 保存QImage到指定路
    bool success = imag.save(fileName); // 第二个参数是文件格式,第三个参数是质量,-1代表默认质量

    if (success) {
        qDebug()<<fileName<< "Image saved successfully.";
    } else {
        qDebug() << "Failed to save image.";
    }

    if(exitMark)//判断是否关闭窗口
        return;
    if(remainUrls.isEmpty())//判断剩余下载是否为空
        return;

    QStringList listone;
    listone<<remainUrls.takeFirst();
    downLoadImags(listone);//调用剩余的未下载的,一次只能推一个


}
//在downLoadImags函数中,通过创建多个QNetworkAccessManager实例并发下载图片
void Dialog::handleData(QByteArray & data)
{
    QString str = QString(data);
   // qDebug() << endl << endl << endl << str;

    QRegularExpression regExp("<img[^>]*src=['\"]([^\"']*)['\"][^>]*>");

    QStringList list = str.split("\n");
    urlList.clear();

    for (int i = 0; i < list.size(); ++i) {
        int pos = 0;
        while (true) {
            QRegularExpressionMatch match = regExp.match(list.at(i), pos);
            if (!match.hasMatch()) break;

            pos = match.capturedEnd();
            qDebug() << "pos :" << pos;
            QString url=match.captured(1);//捕获值为1

            if (url.contains("http")) {//简单判断src属性
                // URL是有效的
                QString valuedUrl=match.captured(1);
                qDebug() << "Match1: " << match.captured(1);
                urlList <<valuedUrl;
            }
            else {
                // URL是无效的  相对路径
                QString valuedUrl=extractedDomain+match.captured(1);
                qDebug() << "Match2: " << valuedUrl;
                urlList <<valuedUrl;
                QString valuedUrl2 ="https:"+match.captured(1);
                qDebug() << "Match3: " << valuedUrl2;
                urlList <<valuedUrl2;

            }

        }
}



}
//保存图片
void Dialog::saveImg()
{

    foreach (const QString& url, urlList)
    {
            QImage imag=downLoadImag(url);
            QPixmap zzz=QPixmap::fromImage(imag);
//            QIcon zz(zzz);

//            ui->toolButton->setIcon(zz);
//            ui->toolButton->setIconSize(QSize(ui->toolButton->size()));
            QFileInfo info(url);
            QString fileName =info.fileName();
            // 保存QImage到指定路
            bool success = zzz.save(fileName); // 第二个参数是文件格式,第三个参数是质量,-1代表默认质量

            if (success) {
                qDebug()<<fileName<< "Image saved successfully.";
            } else {
                qDebug() << "Failed to save image.";
            }
    }

}


void Dialog::on_pushButton_clicked()
{
    //获取网页数据
    QByteArray data;
    QString text=ui->lineEdit->text();

    QRegularExpression regex("^https?://[^/]+");//表达式用于匹配以http://或https://开头的头部
    QString inputUrl = text;
    QRegularExpressionMatch match = regex.match(inputUrl);
    if (match.hasMatch()) {
        extractedDomain = match.captured(0);
    }

    za(text,data);//识别网站,返回

    handleData(data);//处理数据

    ui->textEdit->clear();
    ui->textEdit_2->clear();
   // ui->textEdit->setText(data.constData());//加载网页到ui上
    for(int i=0;i<urlList.size();i++)
    {
        ui->textEdit_2->append(urlList[i]);
    }
    //saveImg();   单线程
    downLoadImags(urlList);//保存数据  多线程

}


ui:

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值