Libcurl: Website Auslesen



  • Moin,

    Ich habe diesen Quelltext im Netz gefunden:

    void get_page( const char* url, const char* file_name )
    {
    CURL* easyhandle = curl_easy_init() ;
    
    curl_easy_setopt( easyhandle, CURLOPT_URL, url ) ;
    
    std::FILE* file = std::fopen( file_name, "w" ) ;
    curl_easy_setopt( easyhandle, CURLOPT_WRITEDATA, file ) ;
    
    curl_easy_perform( easyhandle );
    
    curl_easy_cleanup( easyhandle );
    }
    
    int main()
    {
    get_page( "www.research.att.com/~bs/","/tmp/stroustrup_home_page.html" ) ;
    }
    

    Jetzt meine Frage: Wie bekomme ich die Funktion dazu, den Quelltext nicht in einer Datei zu speichern sondern den Quelltext in einen C++-String kopieren ?
    Bei den ganzen Libcurl-Funktionen blickt doch keine Sau(ich) mehr durch...

    Danke,
    Wiesel 🕶



  • CURLOPT_WRITEFUNCTION



  • Danke für deine Antwort.

    #include <cstdlib>
    #include <iostream>
    
    #include <curl/curl.h>
    #include <curl/types.h>
    #include <curl/easy.h>
    
    using namespace std;
    
    size_t  write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
    {
        static int first_time=1;
        char outfilename[FILENAME_MAX] = "body.out";
        static FILE *outfile;
        size_t written;
        if (first_time) {
            first_time = 0;
            outfile = fopen(outfilename,"w");
            if (outfile == NULL) {
                return -1;
            }
            fprintf(stderr,"The body is <%s>\n",outfilename);
        }
        written = fwrite(ptr,size,nmemb,outfile);
        return written;
    }
    
    void get_page( const char* url)
    {
    
    CURL* easyhandle = curl_easy_init() ;
    
    curl_easy_setopt( easyhandle, CURLOPT_URL, url ) ;
    curl_easy_setopt(easyhandle,   CURLOPT_WRITEFUNCTION,&write_data);
    
    curl_easy_perform( easyhandle );
    curl_easy_cleanup( easyhandle );
    
    } 
    
    int main(int argc, char *argv[])
    {
        get_page( "http://www.google.de/ig?hl=de");
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    So langsam verliere ich den Überblick. Wie kann ich erreichen, dass ich einer Funktion den Namen der Website als String übergebe und mir dann die Seite ins Hauptprogramm zurückgegeben wird ?



  • Hi.
    Auch wenn es scheiße klingen mag, für sowas benutze ich immer das PHP Manual. Sollte relativ leicht auf C übertragbar sein: http://de.php.net/curl

    Gruß



  • #include <cstdlib>
    #include <iostream>
    
    #include <curl/curl.h>
    #include <curl/types.h>
    #include <curl/easy.h>
    
    using namespace std;
    
    size_t  write_data(char *ptr, size_t size, size_t nmemb, std::string * targetString)
    {
        if( targetString ){
           targetString->append( ptr, size * nmemb);
           return size * nmemb;
        }
        return 0;
    }
    
    std::string get_page( const char* url)
    {
    std::string result;
    CURL* easyhandle = curl_easy_init() ;
    
    curl_easy_setopt(easyhandle, CURLOPT_URL, url ) ;
    curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA,&result);
    curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION,&write_data);
    
    curl_easy_perform( easyhandle );
    curl_easy_cleanup( easyhandle );
    
    } 
    
    int main(int argc, char *argv[])
    {
        std::string page = get_page( "http://www.google.de/ig?hl=de");
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    So kannst du das in einem String speichern ohne das in einer Datei zwischenspeichern zu müssen.



  • Danke, der Code funktioniert. get_page muss nurnoch "result" zurückgeben.

    Leider habe ich jetzt mit LibCurl das selbe Problem wie mit WinInet und Winsock. Ich lasse in ~100-200 Threads eine liste mit URLs laden und überprüfe, ob in diesen Listen ein gewisser Suchstring vorhanden ist. Soweit funktioniert das auch gut, nur wird das Programm bei den letzten ~10-15 seiten extrem langsam. Er braucht also sehr lange um den Quelltext zu laden und bleibt irgendwann, wenn nurnoch ~2-5 seiten abzuarbeiten sind komplett stehn.

    curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA,&result);
    curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION,&write_data);
    
    curl_easy_setopt(easyhandle, CURLOPT_TIMEOUT, 200);
    
    curl_easy_perform( easyhandle );
    

    CURLOPT_TIMEOUT bringt auch keine Verbesserung und die Timeout-Funktion von WinInet hat auch nicht funktioniert.

    Vieleicht hat ja hier jemand irgendeine Idee, wie das Problem lösen kann...



  • Also wenn da soviele Threads sind würde ich an deiner stelle mit dem curl multi interface arbeiten. Und die ganzen requests gleichzeitig ablaufen lassen.
    Dafür brauchst du keine 100-200 threads.
    Woran das bei deinem Problem liegt kann ich jetzt nicht sagen da du ja in dem code nicht mal die return werte auswertest.

    Ich habe auch nicht soviel zeit das ganze detailiert mit dir durchzugehen.

    Du musst dich halt mal mit libcurl intensiver beschäftigen unter anderem auch wie man select das mit verwendet etc.

    BR
    Vinzenz



  • Wiesel667 schrieb:

    Danke, der Code funktioniert. get_page muss nurnoch "result" zurückgeben.

    Leider habe ich jetzt mit LibCurl das selbe Problem wie mit WinInet und Winsock. Ich lasse in ~100-200 Threads eine liste mit URLs laden und überprüfe, ob in diesen Listen ein gewisser Suchstring vorhanden ist. Soweit funktioniert das auch gut, nur wird das Programm bei den letzten ~10-15 seiten extrem langsam. Er braucht also sehr lange um den Quelltext zu laden und bleibt irgendwann, wenn nurnoch ~2-5 seiten abzuarbeiten sind komplett stehn.

    curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA,&result);
    curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION,&write_data);
    
    curl_easy_setopt(easyhandle, CURLOPT_TIMEOUT, 200);
    
    curl_easy_perform( easyhandle );
    

    CURLOPT_TIMEOUT bringt auch keine Verbesserung und die Timeout-Funktion von WinInet hat auch nicht funktioniert.

    Vieleicht hat ja hier jemand irgendeine Idee, wie das Problem lösen kann...

    könnte es nicht evtl. sein das es gar kein programmier problem ist? solltest du die liste von einem server laden, so könnte es doch sein das er von einer ip nur x verbindungen bzw. x traffic zulässt, und dann deine ip sperrt, wenn auch nur für eine bestimmte zeit?

    lg lolo



  • webseiten betreiber haben idr. etwas dagegen, das man mit einem harvester ihre seiten abgrast 😉



  • evilissimo schrieb:

    std::string page = get_page( "http://www.google.de/ig?hl=de");
    

    bei google kommt doch dann immer so ein mensch oder maschiene captcha wenn ich mich nicht täusch 😕



  • das würd doch dann so in die richtung gehen http://de.wikipedia.org/wiki/Denial_of_Service dagegen muß doch so ein server geschützt sein oder 🙂



  • Denial of Service ? Nö.

    Jede URL aus der Liste wird ja nur ein mal aufgerufen und der Quelltext wird runterladen. Deswegen sollte das Eigentlich kein Problem darstellen.

    Das mit dem Google war auch nur ein Beispiel. Die Seiten die aufgerufen werden haben normalerweise kein Captcha. Bei Google kommt übrigends der "303 -Moved permanently" -Fehler, wenn man zu viele Anfragen Stellt.
    Angenommen, es ist kein Programmierfehler, wie kann ich dann verhindern, dass die letzten ~5 Seiten die nicht runterladen werden können mein Programm blockieren ?

    Soll ich vieleicht einen Thread erstellen der überprüft, ob in einer gewissen zeit ein Quelltext gedownloaded wurde ? Falls dann in dieser Zeit nichts mehr passiert könnte man ja die festgefahrenen Threads durch den neuen Thread beenden. Funktioniert das ? Oder gibt es eine Funktion die eine andere Funktion nur eine gewisse Zeit lang laufen lässt und falls dann noch nichts zurückgegeben wurde wird die Funktion abgebrochen ?



  • Wiesel667 schrieb:

    Angenommen, es ist kein Programmierfehler, wie kann ich dann verhindern, dass die letzten ~5 Seiten die nicht runterladen werden können mein Programm blockieren ?

    kannst du in curl nicht einen timeout setzten wie lang die übertragung max. dauern darf? nachdem du ja sicher ein regex über den string feuerst, sobald der runtergeladen ist, siehst du ja dann ob die übertragung erfolgreich war oder?

    http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTTIMEOUT

    lg lolo


Anmelden zum Antworten