2008-12-23 90 views
26

我想用C/C++编写一个程序,它将动态读取网页并从中提取信息。举个例子,假设你想写一个应用程序来跟踪并记录一次eBay拍卖。有没有简单的方法来抓取网页?提供这种功能的库?有没有简单的方法来解析页面以获取特定的数据?以编程方式读取网页

+6

在C/C++非常困难。即使在对正则表达式,XML解析,HTTP方法等(例如Java)有广泛支持的语言中,它也令人讨厌。至于Ebay,它有一个你应该使用的API。 – cletus 2008-12-23 15:03:29

回答

35

看一看的cURL library

#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。这很容易,并且有一种内置的方式。

+4

+1 for cURL - 我在我的一个C++应用程序中使用了cURL,它可以很好地工作,即使有代理和所有其他可能遇到的障碍。 – BlaM 2008-12-23 15:37:21

+0

建议使用正确的工具进行工作是很好的! – xtofl 2008-12-23 16:02:49

+2

如果curl为空(在上面的例子中),最好返回一个错误。 – 2008-12-23 23:27:45

2

您可以使用套接字编程来实现,但实现可靠地获取页面所需协议的各个部分很困难。最好使用库,如neon。这可能会在大多数Linux发行版中安装。在FreeBSD下使用获取库。

对于解析数据,因为许多页面不使用有效的XML,所以您需要实现启发式,而不是真正的基于yacc的解析器。您可以使用正则表达式或状态转换机器来实现这些。正如你想要做的事情涉及到大量的反复试验,你最好使用脚本语言,比如Perl。由于网络延迟较高,您不会看到任何性能差异。

2

尝试使用库,如Qt,它可以从网络中读取数据并从xml文档中获取数据。 This是如何读取xml提要的示例。例如,您可以使用eBay Feed。

2

有一个可用于Windows的免费TCP/IP库,支持HTTP和HTTPS - 使用它非常简单。

Ultimate TCP/IP

CUT_HTTPClient http; 
http.GET("http://folder/file.htm", "c:/tmp/process_me.htm");  

你也可以得到文件,并将它们存储在内存缓冲区(通过CUT_DataSource派生类)。所有常见的HTTP支持都在那里 - PUT,HEAD等。支持代理服务器和安全套接字一样轻而易举。

3

你没有提及任何平台,所以我给你一个Win32的答案。

从互联网上下载任何东西的一种简单方法是URLDownloadToFileIBindStatusCallback参数设置为NULL。为了使该函数更有用,需要实现回调接口。

14

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; 
}