C语言编写轻量爬虫工具
当我们要使用C语言编写一个定制化轻量爬虫工具得需要结合网络请求、HTML解析和数据处理等步骤。由于是轻量级正常情况下我们将使用C语言标准库以及一些第三方库来简化开发。这样省时省力生态丰富可以帮助大家少走很多弯路。具体细节可以看下面具体细节。下面是一个分步指南和示例代码核心组件1、网络请求使用libcurl库获取网页内容2、HTML解析使用libxml2解析HTML3、数据存储将结果保存到文件或内存4、定制规则通过回调函数实现定制逻辑完整示例代码代码语言javascriptAI代码解释#include stdio.h #include stdlib.h #include string.h #include curl/curl.h #include libxml/HTMLparser.h #include libxml/xpath.h // 存储HTTP响应数据 struct MemoryStruct { char *memory; size_t size; }; // libcurl回调函数 static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize size * nmemb; struct MemoryStruct *mem (struct MemoryStruct *)userp; char *ptr realloc(mem-memory, mem-size realsize 1); if(!ptr) { fprintf(stderr, 内存分配失败\n); return 0; } mem-memory ptr; memcpy((mem-memory[mem-size]), contents, realsize); mem-size realsize; mem-memory[mem-size] 0; return realsize; } // 提取链接的回调函数类型定义 typedef void (*LinkHandler)(const char* url, void* userdata); // 核心爬取函数 void crawl_page(const char* url, LinkHandler handler, void* userdata) { CURL *curl; CURLcode res; struct MemoryStruct chunk {0}; curl_global_init(CURL_GLOBAL_DEFAULT); curl curl_easy_init(); if(curl) { // 设置cURL选项 curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk); curl_easy_setopt(curl, CURLOPT_USERAGENT, Mozilla/5.0 (compatible; MyCrawler/1.0)); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // 执行请求 res curl_easy_perform(curl); if(res ! CURLE_OK) { fprintf(stderr, 请求失败: %s\n, curl_easy_strerror(res)); } else { // 解析HTML文档 htmlDocPtr doc htmlReadDoc((xmlChar*)chunk.memory, url, NULL, HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); if (doc) { xmlXPathContextPtr context xmlXPathNewContext(doc); if (context) { // 查找所有a标签 xmlXPathObjectPtr result xmlXPathEvalExpression((xmlChar*)//a/href, context); if (result) { xmlNodeSetPtr nodeset result-nodesetval; for (int i 0; i nodeset-nodeNr; i) { xmlChar *href xmlNodeListGetString(doc, nodeset-nodeTab[i]-children, 1); if (handler href) { handler((const char*)href, userdata); } xmlFree(href); } xmlXPathFreeObject(result); } xmlXPathFreeContext(context); } xmlFreeDoc(doc); } } curl_easy_cleanup(curl); } free(chunk.memory); curl_global_cleanup(); } // 示例链接处理函数 void print_links(const char* url, void* userdata) { FILE *output (FILE*)userdata; fprintf(output, 发现链接: %s\n, url); } // 主函数 int main(int argc, char *argv[]) { if (argc ! 3) { fprintf(stderr, 用法: %s 目标URL 输出文件\n, argv[0]); return 1; } FILE *output fopen(argv[2], w); if (!output) { perror(无法打开输出文件); return 1; } fprintf(output, 爬取结果: %s\n, argv[1]); crawl_page(argv[1], print_links, output); fclose(output); printf(爬取完成结果已保存至 %s\n, argv[2]); return 0; }编译与运行1、安装依赖库代码语言javascriptAI代码解释# Ubuntu/Debian sudo apt-get install libcurl4-openssl-dev libxml2-dev2、编译程序代码语言javascriptAI代码解释gcc -o mycrawler mycrawler.c -lcurl -lxml23、运行示例代码语言javascriptAI代码解释./mycrawler https://example.com output.txt定制化扩展方向1、过滤特定链接代码语言javascriptAI代码解释void filter_links(const char* url, void* userdata) { if (strstr(url, .pdf)) { printf(跳过PDF文件: %s\n, url); return; } // 其他处理... }2、限制爬取深度代码语言javascriptAI代码解释// 添加depth参数到crawl_page函数 void crawl_page(const char* url, LinkHandler handler, void* userdata, int depth) { if (depth 0) return; // ...获取页面内容... // 递归爬取子链接 crawl_page(new_url, handler, userdata, depth-1); }3、数据提取代码语言javascriptAI代码解释// 修改XPath表达式提取其他数据 xmlXPathEvalExpression((xmlChar*)//h1/text(), context);4、多线程支持使用pthread库创建线程池实现线程安全的队列管理URL