整體流程
curl_easy_init 建立句柄。
- 設定 URL、寫入回呼 (或
CURLOPT_WRITEDATA 指向 FILE*)。
curl_easy_perform 執行抓取,HTML 存檔。
- 讀回檔案至記憶體緩衝區。
strstr 定位 img src="..." 模式,提取首張圖片 URL。
- 第二次
curl 下載圖片二進制內容存檔。
完整代碼 (精簡版)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
size_t write_cb(void *ptr, size_t size, size_t nmemb, FILE *fp) {
return fwrite(ptr, size, nmemb, fp);
}
char* extract_first_img(const char *html) {
const char *pre = "img src=\"";
const char *s = strstr(html, pre);
if (!s) return NULL;
s += strlen(pre);
const char *e = strchr(s, '"');
if (!e) return NULL;
char *url = malloc(e - s + 1);
strncpy(url, s, e - s);
url[e - s] = '\0';
return url;
}
int main(int argc, char **argv) {
if (argc < 2) return 1;
CURL *curl = curl_easy_init();
FILE *fp = fopen("page.html", "wb");
curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_perform(curl);
fclose(fp);
curl_easy_cleanup(curl);
// 讀回 HTML
fp = fopen("page.html", "rb");
fseek(fp, 0, SEEK_END);
long sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *html = malloc(sz + 1);
fread(html, 1, sz, fp);
html[sz] = '\0';
fclose(fp);
char *img_url = extract_first_img(html);
if (img_url) {
printf("圖片 URL: %s\n", img_url);
// 第二次 curl 下載圖片...
free(img_url);
}
free(html);
return 0;
}
編譯與執行
gcc -o crawler crawler.c -lcurl
./crawler "https://example.com"
關鍵技術點
| 項目 | 說明 |
| 寫入回呼 | 直接寫 FILE* 避免大頁面佔用堆積 |
| HTML 解析 | 簡易 strstr 適合固定模式;複雜頁面建議 libxml2/gumbo-parser |
| 相對/絕對 URL | 提取後需配合基礎 URL 拼接 (RFC 3986) |
| 錯誤處理 | 檢查 curl_easy_perform 回傳碼、CURLOPT_ERRORBUFFER |
| HTTPS | 需連結 OpenSSL,curl 自動處理驗證 |
擴展方向
- 多執行緒併發下載 (
curl_multi 介面)。
- 遞迴爬蟲 + 去重集合 (Bloom filter/HashSet)。
- User-Agent、Cookie、Referer 偽裝反爬蟲。
- 斷點續傳 (
CURLOPT_RESUME_FROM)。
總結
libcurl 提供強大、跨平台的 HTTP 客戶端能力。配合簡易字串解析或專業 HTML 解析器,可快速構建網頁資源抓取工具。掌握 CURLOPT_WRITEFUNCTION、錯誤處理、二進制下載等核心 API,是 C 語言網路程式設計必備技能。
- 上一篇文章: C 語言簡易電話簿管理系統完整實作:結構體陣列、指標間接索引、增刪改查分頁顯示
- 下一篇文章: Linux epoll 高併發網路模型深度解析:LT/ET 模式、API 詳解、萬級併發聊天室實戰
Copyright ©
程式碼之家 All Rights Reserved