用C语言编写代码 实现一个简易的 Web 爬虫,从指定的一个初始页面的 URL 出发,执行操作: 获取页面->分析页面->提取链接->获取新页面…… 1.仅考虑获取普通 http 页面 2.链接获取最多 3 层
时间: 2024-03-18 18:41:22 浏览: 100
好的,以下是一个简单的C语言实现,可以从指定的一个初始页面的URL出发,获取页面、分析页面、提取链接、获取新页面,但仅考虑获取普通http页面,并且链接获取最多3层。
需要用到libcurl库,可以使用以下命令进行安装:
```
sudo apt-get install libcurl4-openssl-dev
```
然后,以下是代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#define MAX_DEPTH 3
#define MAX_URL_LENGTH 1000
// 定义全局变量,用于存储已经访问过的链接
char *visited_urls[MAX_URL_LENGTH];
int visited_count = 0;
// 定义函数,用于解析网页内容,提取其中的链接
void get_links(char *html, char *base_url, char **link_list, int *link_count) {
char *pos = html;
char *tag, *href;
int len;
while ((tag = strstr(pos, "<a ")) != NULL) {
href = strstr(tag, "href=");
if (href == NULL) {
break;
}
href += 5;
len = strcspn(href, "\"'> \t\r\n");
if (*(href + len) != '\"') {
continue;
}
char *link = (char *)malloc(len + 1);
strncpy(link, href, len);
*(link + len) = '\0';
if (strstr(link, "http") == NULL) {
char *new_link = (char *)malloc(strlen(link) + strlen(base_url) + 1);
strcpy(new_link, base_url);
strcat(new_link, link);
free(link);
link = new_link;
}
*(link_list + *link_count) = link;
(*link_count)++;
pos = href + len;
}
}
// 定义函数,用于获取页面内容
char *get_html(CURL *curl, char *url) {
CURLcode res;
char *html = NULL;
long code = 0;
double connect_timeout = 5.0;
double timeout = 10.0;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, connect_timeout);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &html);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_func);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} else {
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (code == 200) {
return html;
}
}
return NULL;
}
// 定义函数,用于递归获取页面
void crawl(CURL *curl, char *url, int depth) {
if (depth > MAX_DEPTH) {
return;
}
for (int i = 0; i < visited_count; i++) {
if (strcmp(url, *(visited_urls + i)) == 0) {
return;
}
}
*(visited_urls + visited_count) = url;
visited_count++;
char *html = get_html(curl, url);
if (html == NULL) {
return;
}
char *link_list[MAX_URL_LENGTH];
int link_count = 0;
get_links(html, url, link_list, &link_count);
for (int i = 0; i < link_count; i++) {
char *link = *(link_list + i);
crawl(curl, link, depth + 1);
free(link);
}
free(html);
}
// 定义函数,用于写回调函数
size_t write_callback_func(char *ptr, size_t size, size_t nmemb, void *userdata) {
char *html = (char *)userdata;
if (html == NULL) {
html = (char *)malloc(size * nmemb + 1);
strncpy(html, ptr, size * nmemb);
*(html + size * nmemb) = '\0';
} else {
int len = strlen(html);
html = (char *)realloc(html, len + size * nmemb + 1);
strncpy(html + len, ptr, size * nmemb);
*(html + len + size * nmemb) = '\0';
}
return size * nmemb;
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <url>\n", *argv);
return 1;
}
CURL *curl = curl_easy_init();
crawl(curl, *(argv + 1), 1);
curl_easy_cleanup(curl);
for (int i = 0; i < visited_count; i++) {
printf("%s\n", *(visited_urls + i));
}
return 0;
}
```
这段代码使用了递归方法,从指定的URL出发,获取页面内容,然后分析页面中的链接,递归获取每个链接对应的页面内容,直到达到链接获取最多3层为止。解析页面中的链接使用了正则表达式来实现。
需要注意的是,这段代码可能存在一些问题,例如页面编码问题、链接去重问题、异常处理等,需要根据具体情况进行修改和优化。
阅读全文