C語言自動抓取淘寶商品詳情網頁數據,實現輕松高效爬蟲

你是否曾經遇到過需要大量獲取網頁上的數據,但手動復制粘貼又太過費時費力?那么這篇文章就是為你而寫。今天我們將會詳細討論如何使用C語言實現自動抓取網頁上的數據。本文將會從以下8個方面進行逐步分析討論。

1. HTTP協議的基本原理

在開始之前,我們需要了解HTTP協議的基本原理。HTTP是一種客戶端和服務器端之間傳輸數據的協議,它使用TCP/IP協議作為傳輸層。當客戶端需要訪問某個服務器時,它會向服務器發送一個HTTP請求。服務器在接收到請求后,會返回一個HTTP響應。HTTP請求和響應都是由一個頭部和一個可選的消息體組成。

2.使用C語言發送HTTP請求

在C語言中,我們可以使用libcurl庫來發送HTTP請求。libcurl提供了一系列函數來處理網絡請求,并且支持各種常見的網絡協議,包括HTTP、FTP、SMTP等等。下面是一個簡單的例子:

#include <stdio.h>#include <curl/curl.h>int main(void){ CURL *curl; CURLcode res; curl = curl_easy_init(); if(curl){ curl_easy_setopt(curl, CURLOPT_URL,";); res = curl_easy_perform(curl); if(res != CURLE_OK) fprintf(stderr,"curl_easy_perform() failed:%s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); } return 0;}

這個例子中,我們使用了curl_easy_init函數來初始化一個curl對象。然后,我們使用curl_easy_setopt函數來設置請求的URL。最后,我們使用curl_easy_perform函數來執行請求,并將返回結果存儲在res變量中。

3.使用正則表達式解析HTML

當我們從網頁上獲取到數據后,我們需要對其進行解析。HTML是一種標記語言,因此我們可以使用正則表達式來進行解析。下面是一個簡單的例子:

#include <stdio.h>#include <regex.h>int main(void){  regex_t regex;  int reti;  char msgbuf[100];  const char *pattern ="<title>(.*)</title>";  char *data ="<html><head><title>Example</title></head><body><p>Hello World!</p></body></html>";  reti = regcomp(&regex, pattern, REG_EXTENDED);  if (reti){      fprintf(stderr,"Could not compile regex\n");      return 1;  }  reti = regexec(&regex, data,0, NULL,0);  if (!reti){      puts("Match");      regmatch_t matches[2];      reti = regexec(&regex, data,2, matches,0);      if (!reti){          printf("Match:%.*s\n",(int)(matches[1].rm_eo - matches[1].rm_so),&data[matches[1].rm_so]);      }  }  else if (reti == REG_NOMATCH){      puts("No match");  }  else {      regerror(reti,&regex, msgbuf, sizeof(msgbuf));      fprintf(stderr,"Regex match failed:%s\n", msgbuf);      return 1;  }  regfree(&regex);  return 0;}

這個例子中,我們使用了正則表達式來匹配網頁中的標題。首先,我們使用regcomp函數來編譯正則表達式。然后,我們使用regexec函數來執行匹配操作,并將結果存儲在matches數組中。

4.使用XPath解析HTML

除了正則表達式外,我們還可以使用XPath來解析HTML。XPath是一種用于在XML文檔中進行導航的語言,它也可以用于HTML文檔的解析。下面是一個簡單的例子:

#include <stdio.h>#include <libxml/xpath.h>#include <libxml/HTMLparser.h>int main(void){ char *data ="<html><head><title>Example</title></head><body><p>Hello World!</p></body></html>"; htmlDocPtr doc = htmlReadMemory(data, strlen(data), NULL, NULL, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR); if (doc == NULL){ fprintf(stderr,"Failed to parse document\n"); return 1; } xmlXPathContextPtr context = xmlXPathNewContext(doc); if (context == NULL){ fprintf(stderr,"Failed to create XPath context\n"); xmlFreeDoc(doc); return 1; } xmlXPathObjectPtr result = xmlXPathEvalExpression((const xmlChar*)"//title/text()", context); if (result == NULL){ fprintf(stderr,"Failed to evaluate XPath expression\n"); xmlXPathFreeContext(context); xmlFreeDoc(doc); return 1; } if (xmlXPathNodeSetIsEmpty(result->nodesetval)){ fprintf(stderr,"No match found\n"); xmlXPathFreeObject(result); xmlXPathFreeContext(context); xmlFreeDoc(doc); return 1; } printf("Match:%s\n", result->nodesetval->nodeTab[0]->content); xmlXPathFreeObject(result); xmlXPathFreeContext(context); xmlFreeDoc(doc); return 0;}

這個例子中,我們使用了libxml2庫來解析HTML。首先,我們使用htmlReadMemory函數將HTML文檔讀入內存,并解析成一個DOM樹。然后,我們使用xmlXPathNewContext函數創建一個XPath上下文。接著,我們使用xmlXPathEvalExpression函數來執行XPath表達式,并將結果存儲在result對象中。

5.使用JSON解析數據

當我們從網頁上獲取到數據時,它有可能是JSON格式的。JSON是一種輕量級的數據交換格式,易于閱讀和編寫。我們可以使用cJSON庫來解析JSON數據。下面是一個簡單的例子:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cJSON.h"int main(void){    char *data ="{\"name\":\"John Smith\",\"age\":30,\"hobbies\":[\"reading\",\"swimming\"]}";    cJSON *root = cJSON_Parse(data);    if (root == NULL){        fprintf(stderr,"Failed to parse JSON data\n");        return 1;    }    cJSON *name = cJSON_GetObjectItem(root,"name");    if (name == NULL){        fprintf(stderr,"Failed to get name\n");        cJSON_Delete(root);        return 1;    }    printf("Name:%s\n", name->valuestring);    cJSON *age = cJSON_GetObjectItem(root,"age");    if (age == NULL){        fprintf(stderr,"Failed to get age\n");        cJSON_Delete(root);        return 1;    }    printf("Age:%d\n", age->valueint);    cJSON *hobbies = cJSON_GetObjectItem(root,"hobbies");    if (hobbies == NULL){        fprintf(stderr,"Failed to get hobbies\n");        cJSON_Delete(root);        return 1;    }    int i;    for (i=0; i < cJSON_GetArraySize(hobbies);i++){        cJSON *hobby = cJSON_GetArrayItem(hobbies,i);        printf("Hobby %d:%s\n", i +1, hobby->valuestring);    }    cJSON_Delete(root);    return 0;}
這個例子中,我們使用了cJSON庫來解析JSON數據。首先,我們使用cJSON_Parse函數將JSON數據解析成一個cJSON對象。然后,我們使用cJSON_GetObjectItem函數來獲取對象中的屬性。最后,我們使用cJSON_GetArrayItem函數來獲取數組中的元素。6.使用數據庫存儲數據
當我們從網頁上獲取到數據時,我們可以將其存儲到數據庫中。在C語言中,我們可以使用SQLite庫來操作數據庫。下面是一個簡單的例子:
#include <stdio.h>#include <sqlite3.h>static int callback(void *NotUsed, int argc, char **argv, char **azColName){    int i;    for (i=0; i < argc;i++){        printf("%s=%s\n", azColName[i], argv[i]? argv[i]:"NULL");    }    printf("\n");    return 0;}int main(void){    sqlite3 *db;    char *zErrMsg =0;    int rc;    rc = sqlite3_open("test.db",&db);    if (rc){        fprintf(stderr,"Can't open database:%s\n", sqlite3_errmsg(db));        sqlite3_close(db);        return 1;    }    const char *sql ="CREATE TABLE IF NOT EXISTS users ("                      "id INTEGER PRIMARY KEY,"                      "name TEXT NOT NULL,"                      "age INTEGER NOT NULL)";    rc = sqlite3_exec(db, sql, NULL,0,&zErrMsg);    if (rc != SQLITE_OK){        fprintf(stderr,"SQL error:%s\n", zErrMsg);        sqlite3_free(zErrMsg);        sqlite3_close(db);        return 1;    }    sql ="INSERT INTO users (name, age) VALUES ('John Smith', 30)";    rc = sqlite3_exec(db, sql, NULL,0,&zErrMsg);    if (rc != SQLITE_OK){        fprintf(stderr,"SQL error:%s\n", zErrMsg);        sqlite3_free(zErrMsg);        sqlite3_close(db);        return 1;    }    sql ="SELECT * FROM users";    rc = sqlite3_exec(db, sql, callback,0,&zErrMsg);    if (rc != SQLITE_OK){        fprintf(stderr,"SQL error:%s\n", zErrMsg);        sqlite3_free(zErrMsg);        sqlite3_close(db);        return 1;    }    sqlite3_close(db);    return 0;}
這個例子中,我們使用了SQLite庫來操作數據庫。首先,我們使用sqlite3_open函數打開一個數據庫連接。然后,我們使用sqlite3_exec函數執行SQL語句。最后,我們使用回調函數來處理查詢結果。
7.使用多線程提高效率
當我們需要從多個網頁上獲取數據時,我們可以使用多線程來提高效率。在C語言中,我們可以使用pthread庫來創建和管理線程。下面是一個簡單的例子:
#include <stdio.h>#include <pthread.h>void *thread_func(void *arg){    int i;    for (i=0; i < 10;i++){        printf("Thread %d:%d\n",*((int*)arg),i);    }    return NULL;}int main(void){    pthread_t threads[4];    int thread_args[4];    int i;    for (i=0; i <4;i++){        thread_args[i]= i +1;        pthread_create(&threads[i], NULL, thread_func,&thread_args[i]);    }    for (i=0; i <4;i++){        pthread_join(threads[i], NULL);    }    return 0;}

這個例子中,我們使用了pthread庫來創建和管理線程。首先,我們使用pthread_create函數創建一個新的線程,并將thread_args數組中的元素傳遞給線程函數。然后,我們使用pthread_join函數等待線程結束。

8.使用定時器實現定時抓取

當我們需要定時抓取網頁上的數據時,我們可以使用定時器來實現。在C語言中,我們可以使用timer_create函數來創建一個定時器。下面是一個簡單的例子:

#include <stdio.h>#include <signal.h>#include <time.h>void handler(int sig){    printf("Timer expired\n");}int main(void){    struct sigevent sev;    timer_t timerid;    struct itimerspec its;    sev.sigev_notify = SIGEV_SIGNAL;    sev.sigev_signo = SIGUSR1;    sev.sigev_value.sival_ptr =&timerid;    timer_create(CLOCK_REALTIME,&sev,&timerid);    signal(SIGUSR1, handler);    _sec =5;    _nsec =0;    _sec =5;    _nsec =0;    timer_settime(timerid,0,&its, NULL);    while (1){f56ac3d0fc4809ae1c100a6b745ccf4b// do something    }    return 0;}

9.舉例說明:通過C語言進行封裝接口獲取淘寶商品詳情返回值說明

9.1公共參數

名稱類型必須描述
keyString調用key(必須以GET方式拼接在URL中,演示demo地址)
secretString調用密鑰
api_nameStringAPI接口名稱(包括在請求地址中)[item_search,item_get,item_search_shop等]
cacheString[yes,no]默認yes,將調用緩存的數據,速度比較快
result_typeString[json,jsonu,xml,serialize,var_export]返回數據格式,默認為json,jsonu輸出的內容中文可以直接閱讀
langString[cn,en,ru]翻譯語言,默認cn簡體中文
versionStringAPI版本 (復制Taobaoapi2014獲取API SDK文件)

9.2 請求示例(C語言)

#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include<curl/curl.h>int main(){CURL *curl;  CURLcode res;   struct curl_slist *headers=NULL; char url[] = "https://api.xxxxx.cn/taobao/item_get/?key=<您自己的apiKey>&secret=<您自己的apiSecret>&num_iid=商品ID&is_promotion=1";curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if(curl) {curl_easy_setopt(curl, CURLOPT_URL,url);headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl);if(res != CURLE_OK){printf("curl_easy_perform(): %s\n",curl_easy_strerror(res));                     }curl_easy_cleanup(curl);          }curl_global_cleanup();return 0;
}

通過上面的代碼,我們可以得到一個簡單版的爬蟲程序,它可以從目標網站上抓取內涵段子,并提取出來打印輸出。

注意事項及高級技巧
在使用PHP編寫爬蟲程序時,需要注意以下事項:

遵循目標網站的robots.txt協議,不要濫用爬蟲而導致網站崩潰;
使用cURL等工具時,需要設置User-Agent、Referer等頭部信息,模擬瀏覽器行為;
對獲取的HTML數據進行適當的編碼處理,防止亂碼問題;
避免頻繁訪問目標網站,操作過于頻繁可能會被網站封禁IP地址;
如需獲取驗證碼等需要人工干預的內容,需要使用圖像識別技術等高級技巧。
通過以上這些注意事項和高級技巧,我們可以更好地應對不同的爬蟲需求,實現更加高效、穩定的數據采集。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36865.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36865.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36865.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小白到運維工程師自學之路 第七十三集 (kubernetes應用部署)

一、安裝部署 1、以Deployment YAML方式創建Nginx服務 這個yaml文件在網上可以下載 cat nginx-deployment.yaml apiVersion: apps/v1 #apiVersion是當前配置格式的版本 kind: Deployment #kind是要創建的資源類型&#xff0c;這里是Deploymnet metadata: #metadata是該資源…

Photoshop多圖片與多窗口下排列操作方法

首先&#xff0c;在Photoshop中打開6張圖片&#xff0c;在“窗口”菜單下切換窗口排列狀態&#xff1a; 在 “窗口”菜單下對窗口進行排列&#xff0c;分別呈現如下&#xff1a; &#xff08;一&#xff09;. 點擊“窗口” -> “排列”->"全部垂直拼貼": &am…

本地oracle登錄賬號鎖定處理,the account is locked

1.打開cmd命令窗口 2.打開sqlplus: sqlplus /nolog(加/nolog是不登錄服務器的意思&#xff0c;不加就需要輸賬號密碼) 3.切換到管理員&#xff1a;conn / as sysdba; 第2步第3步可以合并&#xff0c;直接使用sysdba登錄&#xff1a;sqlplus / as sysdba; 4.解鎖賬號&#x…

大端和小端

大端和小端 大端&#xff08;Big Endian&#xff09;和小端&#xff08;Little Endian&#xff09;是兩種不同的字節序排列方式&#xff0c;用于解釋多字節數據在內存中的存儲順序。 在大端字節序中&#xff0c;高位字節&#xff08;最高有效位&#xff09;存儲在低位地址&am…

1. 兩數之和

題目&#xff1a; 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你可以假設每種輸入只會對應一個答案。但是&#xff0c;數組中同一個元素在答案里不能重復出現。 你…

如何從cpu改為gpu,pytorch,cuda

1.cmd輸入nvcc -V 2.得到 cuda版本后&#xff0c;去pytorch官網 3.根據自己的cuda進行選擇 4.復制上述鏈接&#xff0c;進入cmd 5.cmd中輸入activate XXX,這里的"XXX"指代自己在工程中用到的環境 6.進入后&#xff0c;將剛才鏈接粘貼&#xff0c;回車等待下載結束 …

qt實現截取屏幕

利用qt提供的函數實現截屏: QPixmap QPixmap::grabWindow(WID window, int x 0, int y 0, int width -1, int height -1) window: 表示窗口ID號 x、y: 截取屏幕的其實坐標 width:截取屏幕的寬度 -1表示當前窗口寬度 height:截取屏幕的高度 -1表示當前窗口高度 示例…

《高性能MySQL》——查詢性能優化(筆記)

文章目錄 六、查詢性能優化6.1 查詢為什么會慢6.2 慢查詢基礎&#xff1a;優化數據訪問6.2.1 是否向數據庫請求了不需要的數據查詢不需要的記錄多表關聯時返回全部列總是取出全部列重復查詢相同的數據 6.2.2 MySQL 是否在掃描額外的記錄響應時間掃描的行數與返回的行數掃描的行…

新增守護進程管理、支持添加MySQL遠程數據庫,支持PHP版本切換,1Panel開源面板v1.5.0發布

2023年8月14日&#xff0c;現代化、開源的Linux服務器運維管理面板1Panel正式發布v1.5.0版本。 在這個版本中&#xff0c;1Panel新增了守護進程管理功能&#xff1b;支持添加MySQL遠程數據庫&#xff1b;支持添加FTP/S和WebDAV的SFTP服務&#xff1b;支持PHP版本切換。此外&am…

jupyter打開ipynb后,還沒有運行cell,反復報錯

今天遇到了一個比較奇怪的問題&#xff1a; 這個原因是當前目錄下有一個code.py的文件&#xff0c;一旦打開ipynb&#xff0c;就是先執行code.py&#xff0c;而且遇到報錯&#xff0c;還會反復執行&#xff0c;導致內核崩潰。

創建一個 React+Typescript 項目

接下來 我們來一起探索一下用TypeScript 來編寫react 這也是一個非常好的趨勢&#xff0c;目前也非常多人使用 那么 我們就先從創建項目開始 首先 我們先找一個 或者 之前創建一個目錄 用來放我們的項目 然后 在這個目錄下直接輸入 例如 這里 我想創建一個叫 tsReApp 的項目…

Leangoo領歌敏捷工具全面開啟免費模式

轉發自&#xff1a;Leangoo.com 為了更好的服務敏捷社區&#xff0c;更好的幫助敏捷企業加速產業升級&#xff0c;更好的幫助企業打造敏捷團隊&#xff0c;Leangoo領歌軟件團隊版和企業版全面開啟永久免費模式&#xff0c;同時&#xff0c;Leangoo領歌仍然繼續提供專業的私有部…

面向對象設計與分析40講(20)消息驅動編程和事件驅動編程模型

文章目錄 消息驅動編程事件驅動編程消息驅動和事件驅動的區別 消息驅動編程 消息驅動是一種編程模型&#xff0c;它基于事件和消息的傳遞來驅動程序的執行流程。在消息驅動的模型中&#xff0c;系統中的各個組件&#xff08;或對象&#xff09;通過發送和接收消息進行通信和協…

matplotlib繪制位置-時序甘特圖

文章目錄 1 前言2 知識點2.1 matplotlib.pyplot.barh2.2 matplotlib.legend的handles參數 3 代碼實現4 繪制效果5 總結參考 1 前言 這篇文章的目的是&#xff0c;總結記錄一次使用matplotlib繪制時序甘特圖的經歷。之所以要繪制這個時序甘特圖&#xff0c;是因為22年數模研賽C…

【IDEA問題】下載不了源代碼

引出問題 最近不知道怎么打開 IDEA&#xff0c;本想查看源代碼&#xff0c;然后點擊下載源碼&#xff0c;總是報找不到此對象的源代碼。百度找了半天&#xff0c;GPT問了半天還是解決不了&#xff0c;直到遇到了這篇&#xff1a;idea中無法下載源碼問題解決&#xff0c;終于得…

取證--實操

2022年美亞杯個人賽 運用軟件DB Browser for SQLite &#xff08;一款用于查看SQLlite數據庫文件的瀏覽器工具&#xff09; 火眼&#xff0c;盤古石手機取證系統等 案件詳情 于2022年10月&#xff0c;有市民因接獲偽冒快遞公司的電郵&#xff0c;不慎地于匪徒架設的假網站提…

網絡安全 Day31-運維安全項目-容器架構下

容器架構下 6. Dockerfile6.1 Docker自動化DIY鏡像之Dockerfile1) 環境準備2) 書寫Dockerfile內容3&#xff09; 運行Dockerfile生成鏡像4) 運行容器5) 小結 6.2 案例14&#xff1a;Dockerfile-RUN指令1) 書寫Dockerfile2) 構建鏡像3) 啟動容器4) 測試結果 6.3 Dockerfile指令 …

騰訊面試題算法還原【游戲安全】

本題的參考鏈接&#xff1a;https://share.weiyun.com/5Xg2b7v 其實拿到這個題我就感覺在哪里看過&#xff0c;后來想想是在旺仔那里看到的&#xff0c;以下是旺仔寫的分析過程可以參考一下https://bbs.kanxue.com/thread-276536.htm 但是這個題要比旺仔拿到的那個要增加些許…

Flowable 6.8.0中主要數據表及其字段

在Flowable 6.8.0中&#xff0c;以下是每個表的作用并列出每張表的所有字段及其含義&#xff1a; act_evt_log (用于記錄流程引擎事件的日志) log_nr&#xff1a;日志編號type&#xff1a;事件類型proc_def_id&#xff1a;流程定義IDproc_inst_id&#xff1a;流程實例IDexecuti…

AI 繪畫Stable Diffusion 研究(七) 一文讀懂 Stable Diffusion 工作原理

大家好&#xff0c;我是風雨無阻。 本文適合人群&#xff1a; 想要了解AI繪圖基本原理的朋友。 對Stable Diffusion AI繪圖感興趣的朋友。 本期內容&#xff1a; Stable Diffusion 能做什么 什么是擴散模型 擴散模型實現原理 Stable Diffusion 潛擴散模型 Stable Diffu…