首页 > 其他分享 >C语言多线程爬虫代码示例

C语言多线程爬虫代码示例

时间:2023-06-05 10:24:09浏览次数:42  
标签:示例 URL C语言 mem curl 多线程 com example size

使用C语言编写多线程爬虫能够同时处理多条数据,提高了爬虫的并发度和效率。在编写多线程爬虫时仍需要注意线程安全性和错误处理机制,并根据系统资源和目标网站的特点调整线程数和优化并发策略,以提高程序效率和稳定性。

以下是一个使用C语言多线程编写的简单爬虫示例,实现了并发爬取多个页面的功能:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>

#define MAX_URL_NUM 10 // 最大URL数量
#define MAX_URL_LENGTH 256 // URL最大长度// URL列表
const char *url_list[MAX_URL_NUM] = {"https://www.example.com/page1.html", 
                                     "https://www.example.com/page2.html", 
                                     "https://www.example.com/page3.html",
                                     "https://www.example.com/page4.html",
                                     ".example.com/page5.html",
                                     "https://www.example.com/page6.html",
                                     "https://www.example.com/page7.html",
                                     "https://www.example.com/page8.html",
                                     "https://www.example.com/page9.html",
                                     "https://www.example.com/page10.html"};

// 线程参数结构体
typedef struct {
    char url[MAX_URL_LENGTH];
    int thread_id;
} ThreadArgs;

// 数据缓冲区结构体
typedef struct {
    char *data;
    size_t size;
} MemoryStruct;

// 获取页面响应的回调函数
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    MemoryStruct *mem = (MemoryStruct *) userp;

    mem->data = realloc(mem->data, mem->size + realsize + 1);
    if (mem->data == NULL) {
        /* out of memory! */
        printf("not enough memory (realloc returned NULL)\n");
        return 0;
    }

    memcpy(&(mem->data[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->data[mem->size] = 0;

    return realsize;
线程函数
static void *CrawlThreadFunc(void *args) {
    ThreadArgs *targs = (ThreadArgs *) args;
    char *url = targs->url;
    int thread_id = targs->thread_id;
    CURL *curl;
    CURLcode res;
    MemoryStruct chunk;

    printf("Thread %d: Downloading %s\n", thread_id, url);

    chunk.data = malloc(1);  /* will be grown as needed by the realloc above */
    chunk.size = 0;           /* no data at this point */

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            printf("Thread %d: Download failed: %s\n", thread_id, curl_easy_strerror(res));
        } else {
            printf("Thread %d: Download succeeded, fetched %lu bytes of data\n", thread_id, (unsigned long)chunk.size);
        }

        curl_easy_cleanup(curl);
    }
    
    free(chunk.data);
    pthread_exit(NULL);
}

int main(int argc, char **argv) {
    pthread_t threads[MAX_URL_NUM];
    int rc, i;
    ThreadArgs targs[MAX_URL_NUM];

    // 初始化库
    curl_global_init(CURL_GLOBAL_ALL);

    // 创建子线程并执行爬虫
    for (i = 0; i < MAX_URL_NUM; i++) {
        strncpy(targs[i].url, url_list[i], MAX_URL_LENGTH-1);
        targs[i].thread_id = i;
        rc = pthread_create(&threads[i], NULL, CrawlThreadFunc, (void *) &targs[i]);
        if (rc) {
            printf("Error: return code from pthread_create() is %d\n", rc);
            exit(EXIT_FAILURE);
        }
    }

    // 等待子线程完成
    for (i = 0; i < MAX_URL_NUM; i++) {
        rc = pthread_join(threads[i], NULL);
        if (rc) {
            printf("Error: return code from pthread_join() is %d\n", rc);
            exit(EXIT_FAILURE);
        }
    }

    // 清理库并退出程序
    curl_global_cleanup();
    printf("All downloads complete!\n");
    exit(EXIT_SUCCESS);
}

在以上示例中,我们使用了libcurl库来发起HTTP请求和接收响应。为了方便演示,我们直接预定义了10个URL,并启动10个线程并行执行爬虫任务。实际项目中,可以通过读取配置文件或从命令行参数中获取URL列表,并根据系统资源、网络质量等因素自适应地调整并发度。

在实现过程中,需要注意线程安全性和错误处理机制,避免出现死锁、内存泄漏等问题。

标签:示例,URL,C语言,mem,curl,多线程,com,example,size
From: https://www.cnblogs.com/q-q56731526/p/17457145.html

相关文章

  • C语言写网络爬虫总体思路
    使用C语言编写爬虫可以实现网络数据的快速获取和处理,适用于需要高效处理海量数据的场景。与其他编程语言相比,C语言具有较高的性能和灵活性,可以进行底层操作和内存管理,适合处理较复杂的网络请求和数据处理任务。但是,使用C语言编写爬虫也存在一些挑战。C语言的语法较为复杂,需要较高的......
  • Java:从单线程计数器到多线程数据同步synchronized和原子类Atomic
    (目录)使用单线程单线程修改计数器的值,没有发生问题,每次运行结果都是10000,不过程序耗时较长packagecom.example;/***计数器*/classCounter{privatestaticlongcount;publicstaticlonggetCount(){returncount;}publicstaticv......
  • C语言写网络爬虫总体思路
    使用C语言编写爬虫可以实现网络数据的快速获取和处理,适用于需要高效处理海量数据的场景。与其他编程语言相比,C语言具有较高的性能和灵活性,可以进行底层操作和内存管理,适合处理较复杂的网络请求和数据处理任务。但是,使用C语言编写爬虫也存在一些挑战。C语言的语法较为复杂,需要较高......
  • 必知必会:多线程
    1.线程的6种状态(1)New:初始状态,线程被创建,但是还没调用start方法。(2)Running:就绪状态和运行状态,统称为运行状态(3)Blocked:阻塞状态(4)Waiting:等待状态,需要等待其他线程做出特定的动作(通知或中断)。(5)Time-Waiting:超时等待状态,表示可以在指定的时间自行返回。(6)Terminated:终止状态,表示当前......
  • 【电商api接口京东系列】获取推荐商品列表+获得商品评论演示示例
    数据采集是指获取和整理各种数据的过程,这些数据可以来自各种来源,例如互联网、社交媒体、传统媒体、设备传感器、企业内部系统等。通常,数据采集是企业或组织重要的商业活动之一。它可以帮助企业了解客户需求、产品趋势、市场机会,以及竞争对手的情况,进而做出更加明智的商业决策。......
  • WPF入门教程系列二十七 ——DataGrid使用示例MVVM模式(4)
    WPF入门教程系列目录WPF入门教程系列二——Application介绍WPF入门教程系列三——Application介绍(续)WPF入门教程系列四——Dispatcher介绍WPF入门教程系列五——Window介绍WPF入门教程系列十一——依赖属性(一)WPF入门教程系列十五——WPF中的数据绑定(一)   ......
  • Flex 4.6 XML搜索、匹配示例,完整代码
    效果见图初始化界面输入“设置”,进行搜索、匹配后界面下面是代码<?xmlversion="1.0"encoding="utf-8"?><s:Applicationxmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="l......
  • Flex/AS3/flash player支持屏蔽右键菜单,自定义菜单,并设置相应的菜单事件(示例,图解)..
    播放器版本11.2以后支持右键菜单屏蔽及自定义菜单1.更新播放器,11.2以上版本http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_3.swchttp://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_4.swchttp://download.macro......
  • Java反编译工具Jad的下载与使用示例
    场景Java反编译工具-JD-GUI下载以及使用:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/84317051上面讲过Java反编译工具JD-GUI的使用,如果使用jad并通过命令如何实现反编译。 为了验证Java开发手册中为什么不推荐使用+进行字符串拼接,我们编写示例代码并编译和......
  • C语言gcc编译环境搭建
     第一步,根据以下链接下载gcc工具包;gcc工具包下载地址:链接:https://pan.baidu.com/s/1JqEjakTcWLPv7p6zkah6sA提取码:k4d2第二步,将下载好的工具包解压到本地;第三步,找到gcc工具包目录下的bin文件夹所在的目录,将该路径添加到系统的环境变量中; 第四步,打开CMD,输入gcc,,验证......