libcurl出现CURLcode 23 CURLE_WRITE_ERROR错误 以及每次抓取网页长度不一致问题

使用libCURL时调用curl_easy_perform返回的CURLcode为23错误。
查看得知是CURLE_WRITE_ERROR,写文件错误。
估计是使用curl_easy_setopt时设置CURLOPT_WRITEFUNCTION或者CURLWRITEDATA时有问题,结果找了半天也没有发现。
最后发现是够早的WRITEFUNC有问题:
错误:
size_t function(const void *ptr, size_t size, size_t nmemb, const void *stream)
     … … … …
     fwrite(ptr, size, nmemb, (FILE *)stream);
     … … … …
     return 0;
}
返回值出错,正确的返回值应该是文件写入的大小
return size * nmemb;
否则就会报上面的错误。
正确函数:
size_t function(const void *ptr, size_t size, size_t nmemb, const void *stream)
     int ret;
     … … … …
     ret = fwrite(ptr, size, nmemb, (FILE *)stream);
     … … … …
     return ret;
}
这样,在fwrite正确执行时,就不会报错了。

============================================================

//headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate");

问题找出来了,原来网页是被压缩了,把图中的语句注释掉,服务器就不会返回压缩过的网页。这样每次获取的网页内容都是正常的了。之前也想过是不是网页请求头部出问题了,只是改过的地方不对,关键是自己对这些字段信息的设置也不懂。现在我要好好去学习一下


抓取网页内容需要用到网络编程和HTML解析技术,这里给出一个基于C++的示例代码,使用了libcurl和libxml2库: ```cpp #include <curl/curl.h> #include <libxml/HTMLparser.h> #include <iostream> #include <string> #include <vector> // 回调函数,处理libcurl返回的网页内容 static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { size_t realsize = size * nmemb; std::string* str = (std::string*)userp; str->append((char*)contents, realsize); return realsize; } // 解析HTML内容,提取中文文本 static void ParseHtml(const std::string& html, std::vector<std::string>& result) { htmlDocPtr doc = htmlReadDoc((xmlChar*)(html.c_str()), NULL, NULL, HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); if (!doc) { std::cerr << "Failed to parse HTML" << std::endl; return; } xmlNodePtr cur = xmlDocGetRootElement(doc); while (cur && cur->type != XML_ELEMENT_NODE) { cur = cur->next; } while (cur) { if (cur->type == XML_ELEMENT_NODE) { if (xmlStrcmp(cur->name, (const xmlChar*)"script") == 0 || xmlStrcmp(cur->name, (const xmlChar*)"style") == 0) { // 忽略脚本和样式标签 cur = cur->next; continue; } xmlChar* text = xmlNodeGetContent(cur); if (text) { std::string str = (char*)text; int len = str.length(); for (int i = 0; i < len; i++) { if (str[i] >= 0x4e00 && str[i] <= 0x9fa5) { // 只保留中文字符 result.push_back(str.substr(i, 1)); } } xmlFree(text); } } cur = cur->next; } xmlFreeDoc(doc); } int main(int argc, char** argv) { if (argc < 2) { std::cerr << "Usage: " << argv[0] << " url" << std::endl; return 1; } CURL* curl = curl_easy_init(); if (!curl) { std::cerr << "Failed to initialize libcurl" << std::endl; return 1; } std::string html; std::vector<std::string> result; curl_easy_setopt(curl, CURLOPT_URL, argv[1]); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &html); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "Failed to fetch URL: " << curl_easy_strerror(res) << std::endl; curl_easy_cleanup(curl); return 1; } ParseHtml(html, result); for (const auto& str : result) { std::cout << str; } std::cout << std::endl; curl_easy_cleanup(curl); return 0; } ``` 这个代码可以从命令行接收一个网页链接作为参数,抓取网页内容并解析出中文文本,输出到标准输出。你可以根据自己的需求修改代码,比如改为从文件中读取链接列表,抓取多个网页的内容等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值