2008-12-23 88 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; 
}