Kirjautuminen

Haku

Tehtävät

Koodit: C++: Sivun lataus libcurl-kirjastolla

Kirjoittaja: Metabolix

Kirjoitettu: 20.09.2013 – 12.11.2013

Tagit: kirjaston käyttö, koodi näytille, vinkki

Yleinen kysymys on, miten C++:lla ladataan tiedosto netistä. Eräs tapa on cURL-projektin tuottaman libcurl-kirjaston käyttö. Sama kirjasto sopii hyvin moneen muuhunkin nettitouhuun kuten lomakkeiden lähetykseen ja selaimen matkimiseen, ja kirjaston sivuilla on esimerkkejä.

Kirjasto pitää tietenkin ensin ladata ja asentaa. Linuxissa se usein onkin valmiina. Lähdekoodin saa kirjaston lataussivulta, ja valmis joskin vanhentunut versio Windowsiin MinGW-kääntäjälle (Code::Blocks- ja Dev-C++-ympäristöille) on Devpaks.org-sivustolla. Lisäksi ohjelmaan täytyy liittää oikea otsikkotiedosto (curl/curl.h) sekä linkitysvaiheessa oikea kirjasto (curl, esim. g++-kääntäjälle parametri -lcurl).

Alla on kattavasti kommentoituna funktio, jolla voi ladata netistä sivun merkkijonoksi. Myös binääridatan lataaminen toimii aivan hyvin. Ohjelman main-funktiossa alustetaan libcurl, ladataan malliksi Ohjelmointiputkan etusivu ja tulostetaan siitä palanen.

#include <string>
#include <stdexcept>
#include <iostream>

// Kirjaston otsikko tarvitaan.
#include <curl/curl.h>

/**
 * Lataa sivun netistä libcurl-kirjastolla. Ennen käyttöä libcurl pitää alustaa.
 *
 * @param url sivun osoite
 * @return sivun sisältö
 * @throw std::runtime_error virheen sattuessa
 */
std::string download_with_curl(std::string const& url) {
	// Alustetaan uusi CURL-olio.
	CURL *curl_handle = curl_easy_init();

	// Asetetaan haettava osoite.
	curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());

	// Asetetaan muuttuja, johon ladattava tieto lisätään.
	std::string data;
	curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data);

	// Määritellään ja asetetaan funktio, jolla CURL lisää tietoa muuttujaan.
	// (CURL toimii näin siksi, että isoja tiedostoja ei kannata ollenkaan
	// ladata muistiin vaan kirjoittaa suoraan levylle. Lisäksi näin tietoa
	// voi tarvittaessa käyttää sitä mukaa, kun lataus etenee.)
	struct string_writer {
		// Parametrit: uusi data, datan koko (size * count), oma osoitin.
		// Paluuarvo: lisätyn datan koko.
		static size_t write(void *new_data, size_t size, size_t count, void *ptr) {
			try {
				std::string* data = (std::string*)ptr;
				data->insert(0, (char*) new_data, size * count);
				return count;
			} catch (...) {
				return 0;
			}
		}
	};
	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, string_writer::write);

	// Suoritetaan pyyntö.
	CURLcode curl_code = curl_easy_perform(curl_handle);

	// Tuhotaan CURL-olio.
	curl_easy_cleanup(curl_handle);

	// Jos pyyntö epäonnistui, heitetään poikkeus.
	if (curl_code != CURLE_OK) {
		throw std::runtime_error(curl_easy_strerror(curl_code));
	}

	// Muuten palautetaan data.
	return data;
}

int main(int argc, char** argv) {
	// Alustetaan libcurl.
	if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
		std::cerr << "Virhe libcurlin alustuksessa!" << std::endl;
		return 1;
	}
	try {
		// Yritetään ladata Ohjelmointiputkan etusivu.
		std::string html = download_with_curl("https://www.ohjelmointiputka.net/");
		// Tulostetaan sivun nimi (<title>...</title>).
		std::string::size_type s0 = html.find("<title>"), s1 = html.find("</title>");
		if (s0 == std::string::npos || s1 == std::string::npos) {
			std::cout << "Ei title-tagia!" << std::endl;
		} else {
			std::cout << html.substr(s0, s1 - s0 + 8) << std::endl;
		}
	} catch (std::runtime_error& error) {
		std::cerr << "Virhe: " << error.what() << std::endl;
	}
	// Suljetaan libcurl.
	curl_global_cleanup();
}

Ohjelman voi kääntää Linuxissa näin:

g++ koodi.cpp -o ohjelma -lcurl

Käyttö näyttää esimerkiksi tältä:

$ ./ohjelma
<title>Ohjelmointiputka</title>

Kommentit

Rox [04.10.2013 19:01:24]

#

Saitko edes idean täältä..:d

Sun täytys tehdä hyvät ohjeet miten asentaa libcurl/boost/ym kirjastot + WDDK visual studiolle.. :P Tai onhan tuolla ohjeita mutta selkeet Suomenkieliset ois hyvät.

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta