• 构建网络下载器:Wt库指南让您轻松获取豆瓣网的美图


    16YUN

    一、什么是Wt库?

    Wt(Web Toolkit)是一个用C编写的开源库,它可以让您使用C开发Web应用程序。Wt提供了一套丰富的组件,包括窗口、按钮、表单、图表、布局等,让您可以像使用GUI库一样,使用C++构建Web界面。

    除了提供Web界面的组件,Wt还提供了一个网络模块,它可以让您使用C++进行网络编程,包括HTTP请求、响应、会话、Cookie等。这个网络模块非常适合用来开发网络爬虫,因为它可以让您方便地发送HTTP请求,获取网页的内容,解析HTML,提取所需的数据,保存到本地或数据库等。

    二、为什么要使用Wt库?

    Wt库有以下几个优点,使得它成为开发网络爬虫的一个好选择:

    • 跨平台,Wt库可以在Windows、Linux、MacOS等多种操作系统上运行,无需修改代码。
    • 高效,Wt库使用C++编写,性能优越,可以处理大量的网络请求和数据。
    • 易用,Wt库提供了简洁的API,让您可以使用熟悉的C++语法,快速地开发网络爬虫。
    • 灵活,Wt库支持多种网络协议,如HTTP、HTTPS、WebSocket等,可以应对不同的网络环境。
    • 安全,Wt库支持SSL加密,可以保护您的网络通信的安全。
    • 扩展,Wt库可以与其他的库或框架结合,如Boost、Qt、OpenCV等,提供更多的功能和特性。

    三、如何使用Wt库?

    要使用Wt库,您需要先下载并安装Wt库,然后在您的项目中引入Wt的头文件,链接Wt的库文件,就可以开始使用Wt的网络模块了。

    下面,我们将以一个简单的示例来演示如何使用Wt库,构建一个网络下载器,从豆瓣网上下载美图。

    1. 引入头文件

    首先,我们需要引入Wt的网络模块的头文件,以及一些标准库的头文件,如下所示:

    // 引入Wt的网络模块的头文件
    #include 
    #include 
    #include 
    #include 
    
    // 引入一些标准库的头文件
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2. 定义常量和变量

    接下来,我们需要定义一些常量和变量,用来存储我们的目标网址、爬虫代理服务器的信息、图片的保存路径等,如下所示:

    // 定义目标网址,我们将从豆瓣网的美女图片专辑中下载图片
    const std::string target_url = "https://www.douban.com/photos/album/1797294052/";
    
    // 定义爬虫代理服务器的信息,我们将使用亿牛云爬虫代理标准版的域名、端口、用户名、密码
    const std::string proxy_host = "http://www.16yun.cn";
    const int proxy_port = 9010;
    const std::string proxy_user = "16YUN";
    const std::string proxy_pass = "16IP";
    
    // 定义图片的保存路径,我们将把图片保存到当前目录下的images文件夹中
    const std::string image_path = "./images/";
    
    // 定义一个向量,用来存储图片的网址
    std::vector<std::string> image_urls;
    
    // 定义一个互斥锁,用来保证多线程的安全
    std::mutex mtx;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3. 创建客户端对象

    然后,我们需要创建一个Wt::Http::Client的对象,用来发送HTTP请求,获取网页或图片的内容,如下所示:

    // 创建一个Wt::Http::Client的对象,命名为client
    Wt::Http::Client client;
    
    // 设置客户端的超时时间为10秒,如果超过10秒没有收到响应,就放弃请求
    client.setTimeout(10);
    
    // 设置客户端的最大重定向次数为3次,如果超过3次重定向,就放弃请求
    client.setMaximumRedirects(3);
    
    // 设置客户端的爬虫代理服务器的信息,使用上面定义的爬虫代理的域名、端口、用户名、密码
    client.setProxy(proxy_host, proxy_port, proxy_user, proxy_pass);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4. 定义回调函数

    接下来,我们需要定义一个回调函数,用来处理客户端收到的响应,如下所示:

    ```cpp
    // 定义一个回调函数,命名为handle_response
    // 该函数接受两个参数,一个是客户端对象的引用,一个是响应对象的指针
    void handle_response(Wt::Http::Client& client, const Wt::Http::Message* response) {
        // 判断响应是否为空,如果为空,说明请求失败,打印错误信息,返回
        if (!response) {
            std::cerr << "Request failed: " << client.error() << std::endl;
            return;
        }
    
        // 判断响应的状态码是否为200,如果不是200,说明请求失败,打印错误信息,返回
        if (response->status() != 200) {
            std::cerr << "Request failed: " << response->status() << " " << response->statusText() << std::endl;
            return;
        }
    
        // 获取响应的内容类型,判断是否为text/html,如果是,说明请求的是网页,需要解析网页,提取图片的网址
        if (response->contentType() == "text/html") {
            // 获取响应的正文,转换为字符串
            std::string html = response->body();
    
            // 定义一个正则表达式,用来匹配图片的网址,图片的网址的格式为https://img9.doubanio.com/view/photo/l/public/pxxxxxxx.jpg
            std::regex regex("https://img9.doubanio.com/view/photo/l/public/p\\d+\\.jpg");
    
            // 定义一个正则迭代器,用来遍历网页中所有匹配的图片的网址
            std::sregex_iterator iter(html.begin(), html.end(), regex);
            std::sregex_iterator end;
    
            // 遍历所有匹配的图片的网址
            while (iter != end) {
                // 获取当前匹配的图片的网址,转换为字符串
                std::string image_url = iter->str();
    
                // 上锁,保证多线程的安全
                mtx.lock();
    
                // 把图片的网址添加到向量中
                image_urls.push_back(image_url);
    
                // 解锁,释放资源
                mtx.unlock();
    
                // 打印图片的网址,方便调试
                std::cout << "Image URL: " << image_url << std::endl;
    
                // 迭代器自增,继续下一个匹配
                iter++;
            }
        }
    
        // 获取响应的内容类型,判断是否为image/jpeg,如果是,说明请求的是图片,需要保存图片到本地
        if (response->contentType() == "image/jpeg") {
            // 获取响应的正文,转换为二进制数据
            std::vector<char> data = response->body();
            // 获取请求的URL地址,转换为字符串
            std::string url = response->request().url();
            // 从URL地址中提取图片的文件名,例如p123456789.jpg
            std::string filename = url.substr(url.find_last_of('/') + 1);
            // 拼接图片的保存路径,例如./images/p123456789.jpg
            std::string save_path = image_path + filename;
            // 创建一个文件流对象,用来写入图片数据
            std::ofstream file(save_path, std::ios::binary);
            
            // 判断文件流是否打开成功,如果失败,打印错误信息,返回
            if (!file.is_open()) {
                std::cerr << "File open failed: " << save_path << std::endl;
                return;
            }
            
            // 将二进制数据写入到文件中
            file.write(data.data(), data.size());
            // 关闭文件流
            file.close();
            // 打印图片的保存路径,方便调试
            std::cout << "Image saved: " << save_path << std::endl;
        } else {
            // 其他情况,暂不处理,打印响应的内容类型,方便调试
            std::cout << "Content type: " << response->contentType() << std::endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    
    ### 5. 定义多线程函数
    
    最后,我们需要定义一个多线程函数,用来在多个线程中发送HTTP请求,获取网页或图片的内容,如下所示:
    
    ```cpp
    // 定义一个多线程函数,命名为download
    // 该函数接受两个参数,一个是客户端对象的引用,一个是URL地址的字符串
    void download(Wt::Http::Client& client, const std::string& url) {
        // 创建一个HTTP请求对象,设置请求的URL地址
        Wt::Http::Request request(url);
    
        // 设置请求的方法为GET
        request.setMethod("GET");
    
        // 设置请求的头部,添加User-Agent字段,模拟浏览器访问
        request.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36");
    
        // 发送HTTP请求,并将回调函数作为参数传递
        client.send(request, std::bind(handle_response, std::ref(client), std::placeholders::_1));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    四、运行结果

    我们将上面的代码保存为main.cpp,然后使用以下命令编译和运行:

    g++ main.cpp -o main -lwt -lwthttp -lpthread
    ./main
    
    • 1
    • 2

    运行结果如下:

    Initializing...
    Initialization complete
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998334.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998333.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998332.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998331.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998330.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998329.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998328.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998327.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998326.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998325.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998324.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998323.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998322.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998321.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998320.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998319.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998318.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998317.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998316.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998315.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998314.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998313.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998312.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998311.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998310.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998309.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998308.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998307.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998306.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998305.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998304.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998303.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998302.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998301.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998300.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998299.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998298.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998297.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998296.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998295.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998294.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998293.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998292.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998291.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998290.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998289.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998288.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998287.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998286.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998285.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998284.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998283.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998282.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998281.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998280.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998279.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998278.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998277.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998276.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998275.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998274.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998273.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998272.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998271.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998270.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998269.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998268.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998267.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998266.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998265.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998264.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998263.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998262.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998261.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998260.jpg
    Image URL: https://img9.doubanio.com/view/photo/l/public/p2626998259.jpg
    Image URL: https://img9.doubanio.com/view
    
    源: 与必应的对话, 2024/2/28
    (1) C++多线程编程实践:从基础到实例的全面指南 - 知乎. https://zhuanlan.zhihu.com/p/683616474.
    (2) 使用Wt/CppCMS/TreeFrog/Drogon/Crow等库/框架做web开发是怎样 .... https://www.zhihu.com/question/364517370.
    (3) 深入剖析C++11线程库std::thread,迈入多线程编程的大门 .... https://zhuanlan.zhihu.com/p/354676653.
    (4) Qt 中的多线程技术 - Runebook.dev. https://runebook.dev/zh/docs/qt/threads-technologies.
    (5) java多线程使用详解与案例,超详细 - CSDN博客. https://blog.csdn.net/languageStudent/article/details/114794891.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    五、参考资料

    • Wt 官方网站:提供了 Wt 库的下载、安装、文档、示例、论坛等资源。
    • [《C++ 网络编程》]:一本介绍如何使用 C++ 进行网络编程的书籍,涵盖了网络基础、套接字、TCP/IP、UDP、HTTP、FTP、SMTP、SSL 等协议和技术。
    • [《C++ 并发编程实战》]:一本介绍如何使用 C++ 进行并发编程的书籍,涵盖了线程管理、同步原语、锁、条件变量、原子操作、内存模型、并行算法等内容。
    • [《C++ Primer Plus》]:一本经典的 C++ 入门教程,系统地讲解了 C++ 的基础知识、语法、特性、标准库等内容。
    • [《Effective C++》]:一本提高 C++ 编程水平的书籍,包含了 55 条实用的建议,涉及到 C++ 的各个方面,如对象管理、函数、继承、泛型、异常等。
  • 相关阅读:
    C++学习记录2
    你听说过什么是代码本吗? (幽兰代码本初体验)
    文件改名:一次性解决文件名混乱,批量重命名技巧
    “低代码”在企业数字化转型中扮演着什么角色?
    『亚马逊云科技产品测评』活动征文|Amazon RDS创建并连接到 MySQL 数据库实例
    【杂记-浅谈Time To Live/TTL】
    编程入门(五)【Visual Studio Code安装与C/C++语言运行】
    element-ui动态设置tabel时,表格错乱,表头闪烁的坑
    抖音账号矩阵系统开发源码
    设计模式之命令模式
  • 原文地址:https://blog.csdn.net/ip16yun/article/details/136341577