利用libcurl获取新浪股票接口

这篇博客展示了如何利用libcurl库在Ubuntu和OpenWrt系统中通过HTTP GET请求获取新浪股票接口的数据。代码示例中定义了一个回调函数用于处理响应数据,并解析出股票的当前价、昨收价、今开价和今高价等信息。文章还提供了编译和运行代码的Makefile。

参考

利用libcurl获取新浪股票接口, ubuntu和openwrt实验成功(三)
http://blog.chinaunix.net/uid-27194309-id-3987565.html

  1. 利用 CURLOPT_WRITEFUNCTION 设置回调函数, 利用 CURLOPT_WRITEDATA 获取数据指针

完整代码如下:

/*------------------------------------------------------------------------------------------
名称: http_sina_curl_callbak.c
功能: 利用libcurl的回调机制实现sina股票接口. http://curl.haxx.se/libcurl/c/curl_easy_setopt.html

http://hq.sinajs.cn/list=sz150013
http://hq.sinajs.cn/list=sh601318

#libcurl的调试信息
* About to connect() to hq.sinajs.cn port 80 (#0)
* Trying 219.142.78.242...
* connected
* Connected to hq.sinajs.cn (219.142.78.242) port 80 (#0)
> GET /list=sz150001 HTTP/1.1
Host: hq.sinajs.cn
Accept: * *

< HTTP/1.1 200 OK
< Cache-Control: no-cache
< Content-Length: 250
< Connection: Keep-Alive
< Content-Type: application/x-javascript; charset=GBK
<
* Connection #0 to host hq.sinajs.cn left intact
* Closing connection #0

#运行结果:
root@OpenWrt:/xutest# ./http_sina_stock
sz150001: dq = 0.724, jg = 0.730, jd = 0.722, jk = 0.729
sz150013: dq = 0.886, jg = 0.893, jd = 0.885, jk = 0.889
sz150100: dq = 0.981, jg = 0.982, jd = 0.979, jk = 0.980
sz150152: dq = 0.964, jg = 0.967, jd = 0.964, jk = 0.965
sz150018: dq = 0.958, jg = 0.960, jd = 0.957, jk = 0.960
root@OpenWrt:/xutest#
-------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <assert.h>

#define HTTP_GET "GET"
#define HTTP_PUT "PUT"
#define HTTP_HEAD "HEAD"
#define HTTP_POST "POST"
#define HTTP_DELETE "DELETE"
#define HTTP_RET_OK "HTTP/1.1 200 OK\r\n"

#define SINA_HOST "hq.sinajs.cn"
#define SINA_PORT 80

#define ARRAY_COUNT(x) (sizeof(x) / sizeof(x[0]))

typedef struct {
    float price_dq;    //当前价, 取拼音的首字母
    float price_zs;    //昨收价
    float price_jk;    //今开价
    float price_jg;    //今高价
    float price_jd;    //今低价
} stock_info_t;

#define DBG //printf
#define CURL_DBG (0)    //1=开启curl的调试

//-----------------------------------------------------------------------------------------
static void delay_ms(int msec)
{
    struct timeval timeout;

    memset(&timeout, 0, sizeof(struct timeval));
    timeout.tv_sec    = msec / 1000;
    timeout.tv_usec    = (msec % 1000) * 1000;
    select(0, NULL, NULL, NULL, &timeout);
}

size_t callback_get_head(void *ptr, size_t size, size_t nmemb, void *userp)
{
    strcat(userp, ptr);

    return size * nmemb; //必须返回这个大小, 否则只回调一次
}

static char connect_cloud(char *pc_ret, const char *host_addr, const int portno,
    const char *pc_method, struct curl_slist *http_headers)
{
    CURL *curl;
    CURLcode res = CURLE_GOT_NOTHING;

  assert((pc_ret != NULL) && (host_addr != NULL) && (pc_method != NULL));

  //curl_global_init(CURL_GLOBAL_DEFAULT);
  curl = curl_easy_init();
  if (!curl)    {
      fprintf(stderr, "--- curl init Error!\n");
      return 0;
  }

  curl_easy_setopt(curl, CURLOPT_URL, host_addr);
  curl_easy_setopt(curl, CURL_HTTP_VERSION_1_1, 1L);    //HTTP 1.1
  curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);     //设置超时, 单位为秒.
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);     //屏蔽其它信号, makes libcurl NOT ask the system to ignore SIGPIPE signals
    curl_easy_setopt(curl, CURLOPT_HEADER, 1L);         //下载数据包括HTTP头部, The default value for this parameter is 0.
    //curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);    //The default value for this parameter is 1

#if (CURL_DBG == 1)
  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);    //调试用: 显示交互明细,
    //curl_easy_setopt(curl, CURLOPT_HEADER, 1L);    //调试用: 只显示头行的返回
#endif

#if 1
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, pc_method);

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_get_head); //下载数据的回调函数
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, pc_ret);                                //下载数据的指针

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_headers);    //多行的HTTP头部
#endif

  res = curl_easy_perform(curl);
  if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));

    curl_easy_cleanup(curl);

  return 1;
}

int sina_get_stock(char *pc_ret, const char *pc_stockid)
{
    char pc_url[200], ret;

    //组织请求头部, 自动末尾添加'\r\n'
    struct curl_slist *http_headers = NULL;
    http_headers = curl_slist_append(http_headers, "Accept: */*");
    //http_headers = curl_slist_append(http_headers, "Connection: Close");

    //发送请求, 再判断返回值
    //url = hq.sinajs.cn/list=sz150013
    sprintf(pc_url, "%s/list=%s", SINA_HOST, pc_stockid);
    ret = connect_cloud(pc_ret, pc_url, SINA_PORT, HTTP_GET, http_headers);
    //DBG("cloud ret = %s\n", pc_ret);

    //释放 http_headers资源
    curl_slist_free_all(http_headers);

    return(ret);
}

#if 0
/*字符串不同含义的数据用逗号隔开了,按照程序员的思路,顺序号从0开始。
0:”大秦铁路”,股票名字;
1:”27.55″,今日开盘价;
2:”27.25″,昨日收盘价;
3:”26.91″,当前价格;
4:”27.55″,今日最高价;
5:”26.20″,今日最低价;
6:”26.91″,竞买价,即“买一”报价;
7:”26.92″,竞卖价,即“卖一”报价;
8:”22114263″,成交的股票数,由于股票交易以一百股为基本单位,所以在使用时,通常把该值除以一百;
9:”589824680″,成交金额,单位为“元”,为了一目了然,通常以“万元”为成交金额的单位,所以通常把该值除以一万;
10:”4695″,“买一”申请4695股,即47手;
11:”26.91″,“买一”报价;
12:”57590″,“买二”
13:”26.90″,“买二”
14:”14700″,“买三”
15:”26.89″,“买三”
16:”14300″,“买四”
17:”26.88″,“买四”
18:”15100″,“买五”
19:”26.87″,“买五”
20:”3100″,“卖一”申报3100股,即31手;
21:”26.92″,“卖一”报价
(22, 23), (24, 25), (26,27), (28, 29)分别为“卖二”至“卖四的情况”
30:”2008-01-11″,日期;
31:”15:05:32″,时间;*/
#endif

void stock_parse(stock_info_t *stock, const char *pc_data)
{
    char *pc_str, *pc_str1;
    int i;

    assert((stock != NULL) &&(pc_data != NULL));

    //DBG("data = %s\n", pc_data);
    pc_str = strstr(pc_data, HTTP_RET_OK);
    if (pc_str) {
        pc_str += strlen(HTTP_RET_OK);

        pc_str = strstr(pc_str, "\r\n\r\n");
        pc_str += 4;
        DBG("valid str = %s\n", pc_str);

        //解析数据, var hq_str_sz150013="???B,0.899,0.906,0.897,0.903,0.895,0.897,0.898,9739979,8751058.780,2200,0.897,143548,0.896,572900,0.895,625300,0.894,167300,0.893,9800,0.898,60000,0.899,362300,0.900,162500,0.901,217000,0.902,2013-11-06,10:38:44,00";
        pc_str = strchr(pc_str, ',');
        pc_str ++;

        for (i=0; i<5; i++) {
            pc_str1 = strchr(pc_str, ',');
            if (pc_str1) {
                *pc_str1 = '\0';
                switch(i) {
                    case 0: stock->price_jk = atof(pc_str); break;    //今开
                    case 1: stock->price_zs = atof(pc_str); break;    //昨收
                    case 2: stock->price_dq = atof(pc_str); break;    //当前
                    case 3: stock->price_jg = atof(pc_str); break;    //今高
                    case 4: stock->price_jd = atof(pc_str); break;    //今低
                }

                pc_str = pc_str1 + 1;    //指向下个有效数据
            }
            else break;
        }
    }
}

//-------------------------------------------------------------------------------
int main(void)
{
    char pc_ret[1000];
    int i, max;
    stock_info_t stock;

    char *stock_array[] = {"sz150001", "sz150013", "sz150100", "sz150152", "sz150018"};    //改成自己的
    max = ARRAY_COUNT(stock_array);

    for(i=0; i<max; i++) {
        memset(pc_ret, 0x00, sizeof(pc_ret));
        sina_get_stock(pc_ret, stock_array[i]);
        DBG("sina ret OK = %s\n", pc_ret);
        stock_parse(&stock, pc_ret);
        printf("%s: dq = %.3f, jg = %.3f, jd = %.3f, jk = %.3f\n",
                stock_array[i], stock.price_dq, stock.price_jg, stock.price_jd ,stock.price_jk);
    }

    return 1;
}

Makefile:

OPENWRT = 1

ifeq ($(OPENWRT), 1)
    CC = ~/OpenWrt-SDK-ar71xx-for-linux-i486-gcc-4.6-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc
    CFLAGS += -I ~/openwrt-lib/include -L ~/openwrt-lib/lib
    LFLAGS += -lcurl -lcrypto -lz -lssl

else
    CC = gcc
    LFLAGS += -lcurl
endif

CFLAGS += -Wall -O2
#CFLAGS += -g

#可执行文件名和相关的obj文件
APP_BINARY = http_sina_stock
SRCS += http_sina_curl_callback.c
OBJS = $(SRCS:.c=.o)

all: APP_FILE

APP_FILE: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $(APP_BINARY) $(LFLAGS)

.PHONY: clean
clean:
    @echo "cleanning project"
    $(RM) *.a $(OBJS) *~ *.so *.lo $(APP_BINARY)
    @echo "clean completed"

openwrt下运行结果如下

root@OpenWrt:/xutest# ./http_sina_stock
sz150001: dq = 0.724, jg = 0.730, jd = 0.722, jk = 0.729
sz150013: dq = 0.886, jg = 0.893, jd = 0.885, jk = 0.889
sz150100: dq = 0.981, jg = 0.982, jd = 0.979, jk = 0.980
sz150152: dq = 0.964, jg = 0.967, jd = 0.964, jk = 0.965
sz150018: dq = 0.958, jg = 0.960, jd = 0.957, jk = 0.960

1

http://hq.sinajs.cn/list=sh600519
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值