我想用C/C++编写一个程序,可以动态地读取网页并从中提取信息。比如,如果你想写一个应用程序来跟踪和记录 eBay 的拍卖活动,有没有一种简单的方法来抓取网页?是否有提供这种功能的库?还有获取特定数据的简单方法吗?
看看cURL库:
#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, "curl.haxx.se");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
顺便说一句,如果不一定要用C++的话,我鼓励你尝试使用C#或Java。它们更容易且有内置方法。
Windows 代码:
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main (){
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
return 1;
}
SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
struct hostent *host;
host = gethostbyname("www.google.com");
SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(80);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
cout << "Connecting...\n";
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
cout << "Could not connect";
system("pause");
return 1;
}
cout << "Connected.\n";
send(Socket,"GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n"),0);
char buffer[10000];
int nDataLength;
while ((nDataLength = recv(Socket,buffer,10000,0)) > 0){
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
cout << buffer[i];
i += 1;
}
}
closesocket(Socket);
WSACleanup();
system("pause");
return 0;
}
gethostbyname()
。它应该使用getaddrinfo()
并支持IPv4和IPv6。 - Imbueprintf("%.*s", nDataLength, buffer);
,这更加简单、快速、安全。 - Imbue有一个免费的TCP/IP库可用于Windows,支持HTTP和HTTPS - 使用它非常简单。
CUT_HTTPClient http;
http.GET("http://folder/file.htm", "c:/tmp/process_me.htm");
您还可以使用CUT_DataSource
派生类将文件获取并存储在内存缓冲区中。所有常规的HTTP支持都已经准备好了,包括PUT、HEAD等。代理服务器的支持非常简单,安全套接字也是如此。
对于解析数据,由于许多页面不使用有效的XML,您需要使用启发式方法而不是真正的基于yacc的解析器。您可以使用正则表达式或状态转换机来实现这些。因为您正在尝试进行许多试错操作,所以最好使用脚本语言,如Perl。由于网络延迟很高,您不会看到任何性能差异。
你没有提及任何平台,所以我给你一个Win32的答案。
从互联网上下载任何东西的一种简单方法是使用URLDownloadToFile
函数,并将IBindStatusCallback
参数设置为NULL
。为了使该函数更加有用,需要实现回调接口。
QByteArray WebpageDownloader::downloadFromUrl(const std::string& url)
{
QNetworkAccessManager manager;
QNetworkReply *response = manager.get(QNetworkRequest(QUrl(url.c_str())));
QEventLoop event;
QObject::connect(response, &QNetworkReply::finished, &event, &QEventLoop::quit);
event.exec();
return response->readAll();
}
const string webpageText = downloadFromUrl(url).toStdString();
QT += network