21xrx.com
2025-03-21 23:46:29 Friday
文章检索 我的文章 写文章
使用C++爬取数据
2023-07-12 12:22:44 深夜i     23     0
C++ 爬虫 数据抓取 网络请求 数据处理

在当今互联网时代,大数据已经逐渐成为了各个领域发展的必要条件。而在获取大数据的过程中,网络爬虫技术更是必不可少。为了实现自动化采集数据的目标,很多开发者都在探索爬虫的最佳实践。其中,使用C++进行爬取数据就成为了极具技术含量的一种方法。

和其他语言相比,C++的优势在于它的高效性以及强大的内存管理能力。这意味着使用C++可以实现更加稳定、快速的网络爬虫程序,从而大大提升数据采集的效率和数据质量。

下面介绍一些C++爬取数据的基本方法:

1.网络请求

在C++中,使用Winsock库或者libcurl库可以实现网络请求。这两个库分别提供了对TCP/IP协议栈和HTTP协议的支持,使得爬虫能够非常方便地进行网络请求。使用这两个库的代码如下:

Winsock库:

#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
int main()
{
  WSADATA wsaData;
  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    std::cout << "WSAStartup failed" << std::endl;
    return -1;
  
  SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == INVALID_SOCKET) {
    std::cout << "socket() failed" << std::endl;
    WSACleanup();
    return -1;
  }
  sockaddr_in addrServer;
  addrServer.sin_family = AF_INET;
  addrServer.sin_addr.s_addr = inet_addr("127.0.0.1");
  addrServer.sin_port = htons(80);
  if (connect(sock, (sockaddr*)&addrServer, sizeof(addrServer)) == SOCKET_ERROR) {
    std::cout << "connect() failed" << std::endl;
    closesocket(sock);
    WSACleanup();
    return -1;
  }
  std::string strRequest = "GET / HTTP/1.1\r\n";
  strRequest += "Host: www.baidu.com\r\n";
  strRequest += "Connection: close\r\n";
  strRequest += "\r\n";
  send(sock, strRequest.c_str(), strRequest.length(), 0);
  char buf[4096];
  int nRead;
  while ((nRead = recv(sock, buf, sizeof(buf), 0)) > 0) {
    std::cout.write(buf, nRead);
  }
  std::cout << std::endl;
  closesocket(sock);
  return 0;
}

libcurl库:

#include <curl/curl.h>
#include <iostream>
#include <string>
size_t callback(char* ptr, size_t size, size_t nmemb, std::string* str)
{
  str->append(ptr, size * nmemb);
  return size * nmemb;
}
int main()
{
  CURL* curl = curl_easy_init();
  if (curl) {
    std::string strUrl = "http://www.baidu.com";
    std::string strResult;
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &strResult);
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
      std::cout << curl_easy_strerror(res) << std::endl;
    }
    std::cout << strResult << std::endl;
    curl_easy_cleanup(curl);
  }
  return 0;
}

其中,callback函数为回调函数,在数据接收完成后会被调用。代码中使用std::string来存储接收到的数据。

2.网页解析

C++提供了一些用于解析网页的库,例如libxml2和libhtmlcxx等。这些库可以帮助开发者有效地从网页中提取出目标数据。使用libhtmlcxx的代码如下:

#include <htmlcxx/html/ParserDom.h>
#include <iostream>
using namespace htmlcxx;
void PrintDom(const HTML::Node& node)
{
  if (node.isTag()) {
    std::cout << node.tagName() << std::endl;
  }
  for (auto it = node.begin(); it != node.end(); ++it) {
    PrintDom(*it);
  }
}
int main()
{
  std::string strHtml = "<html><body><div><p>hello world</p></div></body></html>";
  HTML::ParserDom parser;
  tree<HTML::Node> dom = parser.parseTree(strHtml);
  PrintDom(dom.root());
  return 0;
}

解析网页使用HTML::ParserDom库的parseTree函数,可以将网页的HTML代码转换成一个DOM树,方便之后的数据提取。

3.数据存储

在爬取数据完成后,数据需要进行存储。C++提供了多种数据存储方式,例如文件、数据库、缓存等。

文件存储:

#include <fstream>
int main()
{
  std::ofstream ofs("data.txt");
  if (!ofs.is_open()) {
    std::cout << "open file failed" << std::endl;
    return -1;
  }
  ofs << "hello world" << std::endl;
  ofs.close();
  return 0;
}

sql数据库存储:

#include <mysql/mysql.h>
#include <iostream>
int main()
{
  MYSQL mysql;
  mysql_init(&mysql);
  if (!mysql_real_connect(&mysql, "localhost", "admin", "password", "testdb", 0, NULL, 0)) {
    std::cout << mysql_error(&mysql) << std::endl;
    return -1;
  }
  std::string strSql = "insert into student(name, age) values ('test', 20)";
  if (mysql_real_query(&mysql, strSql.c_str(), strSql.length()) != 0) {
    std::cout << mysql_error(&mysql) << std::endl;
  }
  mysql_close(&mysql);
  return 0;
}

以MYSQL库为例,使用mysql_real_connect函数连接数据库,使用mysql_real_query函数执行SQL语句进行存储。

总结:

使用C++进行爬虫开发需要掌握TCP/IP、HTTP等相关协议,需要熟悉html、xml等网页解析方法,同时掌握各种数据存储方式。C++的高效性和内存管理能力使得爬虫程序更加稳定,大大提升了数据采集、解析、存储的效率,是一个非常值得探索的爬虫开发方法。

  
  

评论区

请求出错了