web-dev-qa-db-ja.com

プログラムによるWebページの読み取り

Webページを動的に読み取り、そこから情報を抽出するプログラムをC/C++で作成したい。例として、ebayオークションを追跡して記録するためのアプリケーションを作成する場合を想像してください。 Webページを取得する簡単な方法はありますか?この機能を提供するライブラリ?また、ページを解析して特定のデータを取得する簡単な方法はありますか?

32
Howard May

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を試すことをお勧めします。それははるかに簡単で、組み込みの方法があります。

42
Gant

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

HTTPおよびHTTPSをサポートするWindows用の無料のTCP/IPライブラリがあります。これを使用するのは非常に簡単です。

最終的なTCP/IP

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

ファイルを取得して、メモリバッファに保存することもできます(CUT_DataSource派生クラス)。通常のHTTPサポートはすべてあります-PUT、HEADなど。プロキシサーバーのサポートは簡単です。セキュアソケットも同様です。

4
Rob

プラットフォームについては言及していませんので、Win32の回答をお送りします。

インターネットから何かをダウンロードする1つの簡単な方法は、URLDownloadToFileパラメーターをIBindStatusCallbackに設定したNULLです。関数をより便利にするには、コールバックインターフェイスを実装する必要があります。

4
Johann Gerell

ソケットプログラミングでそれを行うことができますが、ページを確実に取得するために必要なプロトコルの部分を実装するのは難しいです。 neon のようなライブラリを使用する方が良いです。これは、ほとんどのLinuxディストリビューションにインストールされる可能性があります。 FreeBSDでは、フェッチライブラリを使用します。

データを解析するには、多くのページが有効なXMLを使用しないため、実際のyaccベースのパーサーではなく、ヒューリスティックを実装する必要があります。これらは、正規表現または状態遷移マシンを使用して実装できます。あなたがやろうとしていることは多くの試行錯誤を伴うので、Perlのようなスクリプト言語を使用するほうが良いでしょう。ネットワークの待ち時間が長いため、パフォーマンスに違いは見られません。

3

ネットワーク経由でデータを読み取り、xmlドキュメントからデータを取得できるQtなどのライブラリを使用してみてください。 This は、XMLフィードの読み取り方法の例です。たとえば、ebayフィードを使用できます。

3
Marius