当前位置: 首页 > news >正文

C语言编写轻量爬虫工具

当我们要使用C语言编写一个定制化轻量爬虫工具,得需要结合网络请求、HTML解析和数据处理等步骤。由于是轻量级,正常情况下我们将使用C语言标准库以及一些第三方库来简化开发。这样省时省力,生态丰富可以帮助大家少走很多弯路。具体细节可以看下面具体细节。

下面是一个分步指南和示例代码:

核心组件

1、网络请求:使用libcurl库获取网页内容

2、HTML解析:使用libxml2解析HTML

3、数据存储:将结果保存到文件或内存

4、定制规则:通过回调函数实现定制逻辑

完整示例代码

代码语言:javascript

AI代码解释

#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、安装依赖库

代码语言:javascript

AI代码解释

# Ubuntu/Debian sudo apt-get install libcurl4-openssl-dev libxml2-dev

2、编译程序

代码语言:javascript

AI代码解释

gcc -o mycrawler mycrawler.c -lcurl -lxml2

3、运行示例

代码语言:javascript

AI代码解释

./mycrawler https://example.com output.txt
定制化扩展方向

1、过滤特定链接

代码语言:javascript

AI代码解释

void filter_links(const char* url, void* userdata) { if (strstr(url, ".pdf")) { printf("跳过PDF文件: %s\n", url); return; } // 其他处理... }

2、限制爬取深度

代码语言:javascript

AI代码解释

// 添加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、数据提取

代码语言:javascript

AI代码解释

// 修改XPath表达式提取其他数据 xmlXPathEvalExpression((xmlChar*)"//h1/text()", context);

4、多线程支持

  • 使用pthread库创建线程池
  • 实现线程安全的队列管理URL
http://www.jsqmd.com/news/801493/

相关文章:

  • 从苹果高通诉讼看蜂窝基带芯片的技术壁垒与专利博弈
  • 瑞祥卡回收:揭秘闲置原因及快速变现的最佳方式 - 团团收购物卡回收
  • 雪花/方型/子弹制冰机实力派厂家推荐:五大品牌实力与产品全解析 - 品牌推荐大师
  • 2026年,口碑爆棚的到家上门做饭体验,究竟有何独特魅力? - 速递信息
  • 从理论到实践:威尔金森功分器的设计与联合仿真优化
  • 效率翻倍!用 ModelSim 2019.2 给 Vivado 2020.2 工程做仿真的几个高级技巧
  • 西安市CPPM注册采购经理证书报名入口,官方渠道查询说明 - 众智商学院课程中心
  • 为什么你需要LRCGET:5步为离线音乐库实现完美歌词同步
  • 别再说 AI 开发就是调接口了!5 种主流模式一次讲清
  • 思源宋体CN免费字体终极指南:7种字重一站式解决方案
  • Nigate:让Mac与Windows硬盘和谐共处的开源桥梁
  • 永辉超市购物卡高价回收,别再浪费你的卡! - 团团收购物卡回收
  • 如何快速制作专业级LRC歌词文件:歌词滚动姬完全指南
  • 2026年LCD液晶屏正规供应商排名,夺盛电子位列其中 - myqiye
  • 物联网项目实战:在Ubuntu 20.04上快速部署Mosquitto MQTT Broker(含客户端测试)
  • GEO优化都覆盖哪些主流AI平台:艾奇在线(艾奇GEO)专业深度解析与行业梳理 - 产业观察网
  • - 2026年5月宁波名表回收市场解析:5家主流机构实力分级测评 - 奢侈品回收测评
  • Rust与Godot引擎集成:使用gdext构建高性能游戏模块
  • Sora 2视频生成质量跃升47%的关键——Gaussian Splatting空间梯度重参数化技术(独家逆向工程报告)
  • 2026年防火包裹优质厂家推荐指南 廊坊中鸿节能科技有限公司优选 防火包裹/防排烟柔性防火包裹/通风管道防火包裹/硅酸铝防火包裹 - 奔跑123
  • 2026年医疗门靠谱厂家排名,河北翱天展现专业实力 - myqiye
  • 多智能体浏览器自动化:基于标签页隔离的MCP服务器设计与实践
  • 东北三省道路划线公司实力盘点:合规施工阵营一览 - 奔跑123
  • 告别软件模拟!用GD32F303硬件I2C驱动AT24C02 EEPROM保姆级教程(附完整代码)
  • KICAD | 告别繁琐BOM整理,这款Interactive HTML BOM插件堪称效率神器
  • 不止于下载:用Active-HDL给你的Lattice FPGA设计做个“体检”(功能仿真实战)
  • 2026年北京宣传片制作公司推荐:权威深度综合解析 - 速递信息
  • 适用于 STM32 系列单片机的 USB DFU 上位机程序
  • 多麦智能制造,自动打包分拣自动化设备费用高吗 - myqiye
  • 搞懂CanOpen PDO映射:从对象字典0x1800/0x1A00配置到实时数据收发(以电机控制为例)