I am wondering if someone could share his experiene on using quandl api_c
to retrieve data:
Below is the sample code:
#include <iostream>
#include "C:\local\quandl.h"
//Reference: https://github.com/zafuer/QuandlAPI_C
int main()
{
quandl ql;
ql.auth("<code>"); // Replace <code> with your own token.
ql.get("GOOG/PINK_TCEHY");
return 0;
}
It does compile, but retrieves in the project path PINK_TCEHY.csv
with unexpected xml
info:
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.4.6 (Ubuntu)</center>
</body>
</html>
Could someone be able to explain such phenomenon?
Best,
答案 0 :(得分:0)
Quandl不再支持HTTP请求,现在请求必须通过HTTPS进行,我使用curl for windows:
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "https://www.quandl.com/api/v3/datasets/WIKI/FB/data");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
对于linux,使用OpenSSL的api将是:
/*
* quandl(linux).h
*
* Created on: 30/09/2013 (Updated on 10/09/2014) ((Revised on 15/08/2016))
* Author: Zhiwei Fu
* Revision: Jose Marqués Fernández http://www.epigijon.uniovi.es/
*/
/* This programme is free software. It is developed by Dr Zhiwei Fu as a product
contributing to quandl.com.
This programme is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY, without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
//OpenSSL required, for install on ubuntu: sudo apt-get install libssl-dev
//for compile: g++ xxx.cpp -std=c++11 -lssl -lcrypto -o xxx
#ifndef QUANDL_H_
#define QUANDL_H_
#include <iostream>
#include <fstream> //for perror()
#include <string> // string for c++
#include <string.h> // for memset()/bzero() For C
#include <sys/socket.h>
#include <netinet/in.h> // for sockaddr_in, hotons
#include <arpa/inet.h> // for inet_addr
#include <netdb.h> //for gethostbyname(), gethostbyaddr()
#include <netinet/tcp.h> // for TCP_NODELAY
#include <time.h> // time.h
// for https
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <stdarg.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
//using namespace std;
class quandl {
public:
quandl(){
};
~quandl(){};
// To store the token in "AuthCode", which is a public variable in the class.
void auth(std::string code){
AuthCode = code;
}
//To download file from the website defined by the first
//argument.
// To determine the website address by the token stored in "code"
// and call the function "download"
void get(std::string code){
//Set optional variables by default
std::string order = "asc";
std::string type = "csv";
std::string website = "https://www.quandl.com/api/v3/datasets/" + code
+ "." + type + "?sort_order=" + order;
if(AuthCode.length() == 0){
std::cout << "It would appear you are\'nt using an authentication"
<< " token. Please visit https://www.quandl.com/help/c++"
<< " or your usage may be limited.\n";
}
else{
website += "&api_key=" + AuthCode;
}
std::string FileName;
int iLength = code.length();
for (int i=0; i < iLength; i++){
if(code.substr(i, 1) == "/"){
FileName = code.substr(i+1, iLength - i -1);
break;
}
}
download(website, FileName, type);
return;
}
// All parameters are prescribed by users.
// 1. Quandl code;
// 2. Ascending/descending order;
// 3. Start date;
// 4. End date;
// 5. Transformation;
// 6. collapse;
// 7. Rows;
// 8. Output type
// There are 7 optional arguments compared to the one above.
void get(std::string code, std::string order, std::string StartDate, std::string EndDate,
std::string transformation, std::string collapse, std::string rows, std::string type){
std::string website = "https://www.quandl.com/api/v3/datasets/" + code
+ "." + type + "?sort_order=" + order;
if(AuthCode.length() == 0){
std::cout << "It appear you are\'nt using an authentication"
<< " token. Please visit https://www.quandl.com/help/api for getting one"
<< " ; otherwise your usage may be limited.\n";
}
else{
website += "&api_key=" + AuthCode;
}
website += "&trim_start=" + StartDate;
website += "&trim_end=" + EndDate;
website += "&transformation=" + transformation;
website += "&collapse=" + collapse;
website += "&rows=" + rows;
std::string FileName;
int iLength = code.length();
for (int i=0; i < iLength; i++){
if(code.substr(i, 1) == "/"){
FileName = code.substr(i+1, iLength - i -1);
break;
}
}
download(website, FileName, type);
}
private:
std::string AuthCode;
// This void function "download" is to download a file from internet.
// The "download" function is developed with a general purpose of downloading
// files from internet. It is based on the socket programming.
void download(std::string website, std::string FileName, std::string FileType){
struct sockaddr_in ServAddr;
struct hostent *ServInf;
int sockfd;
int iMessage = 1048576; //1 MB for the buff storage
char message[iMessage];
std::string request = "GET ";
std::ofstream fid;
int iStart, iEnd, iLength;
SSL_CTX *ctx;
SSL *ssl;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
SSL_load_error_strings();
if(SSL_library_init() < 0){
std::cerr<<"OpenSSL error"<<std::endl;
return;
}
ctx = SSL_CTX_new (SSLv23_client_method ());
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
//To define the server's address.
memset(&ServAddr, 0, sizeof(ServAddr));
std::string host;
iLength = website.length();
iStart = 0; iEnd = iLength - 1;
if(website.substr(0,8) == "https://") iStart = 8;
else if(website.substr(0,7) == "http://") iStart = 7;
for(int i = iStart; i<iLength; i++){
if(website.substr(i, 1)=="/"){
iEnd = i - 1;
break;
}
}
host = website.substr(iStart, iEnd - iStart + 1);
ServInf = gethostbyname(host.c_str());
if(ServInf == NULL){
std::cerr<<"HostName error"<<std::endl;
return;
}
//Get a socket
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
std::cerr<<"Socket error"<<std::endl;
return;
}
memset(&ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_port = htons(443);
ServAddr.sin_addr.s_addr = *(long*)(ServInf->h_addr);
if ( connect(sockfd, (struct sockaddr*)&ServAddr, sizeof(ServAddr)) == -1 ) {
std::cerr<<"Conection error"<<std::endl;
return;
}
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
SSL_connect(ssl);
// To send the request.
request += website + " HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n";
SSL_write(ssl, request.c_str(), request.length());
// To initiate the file.
fid.open((FileName + "." + FileType).c_str());
if(fid.fail()){
std::cerr << "OpeningFile error" << std::endl;
return;
}
// To read dataflow for the file.
int iRecv = 1;
std::string RcvDt;
while (iRecv != 0 && iRecv != -1){
memset(message, '\0', sizeof(message));
iRecv= SSL_read(ssl, message, iMessage);
RcvDt+=std::string(message);
}
std::string initS="\r\n\r\n";
std::string servR="\r\n";
std::size_t found = RcvDt.find(initS);
if (found!=std::string::npos){
RcvDt.erase(0,found+10);
}
while((found!=std::string::npos)&&(found<RcvDt.size()-8)){
found = RcvDt.find(servR);
if(found<(RcvDt.size()-8)){
RcvDt.erase(found,8);
}
}
fid.write(RcvDt.c_str(), RcvDt.size());
// To close the downloaded file
fid.close();
if(iRecv == -1){
std::cerr<<"SSL_read error"<<std::endl;
return;
}
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
}
};
#endif /* QUANDL_H_ */
我希望这会有用
答案 1 :(得分:0)
您可以使用ql_fetcher作为替代轻量级C ++标头库来下载Quandl数据。您还需要将libcurl与您的项目相关联。
在您的情况下,您可以像这样使用它:
#define QL_FETCHER_IMPL // define only once in your project
#include "ql_fetcher"
#include <string>
int main() {
std::string raw_data = ql_fetcher::fetch("PINK_TCEHY", "GOOG")
.api_key("<code>").make().get().str();
return 0;
}