(转)利用libcurl获取新浪股票接口, ubuntu和openwrt实验成功(三)

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

官网文档如下

CALLBACK OPTIONS

CURLOPT_WRITEFUNCTION

Pass a pointer to a function that matches the following prototype: size_t function( char *ptr, size_t size, size_t nmemb, void *userdata); This function gets called by libcurl as soon as there is data received that needs to be saved. The size of the data pointed to by ptr is size multiplied with nmemb, it will not be zero terminated. Return the number of bytes actually taken care of. If that amount differs from the amount passed to your function, it‘ll signal an error to the library. This will abort the transfer and return CURLE_WRITE_ERROR.

From 7.18.0, the function can return CURL_WRITEFUNC_PAUSE which then will cause writing to this connection to become paused. See curl_easy_pause(3) for further details.

This function may be called with zero bytes data if the transferred file is empty.

Set this option to NULL to get the internal default function. The internal default function will write the data to the FILE * given with CURLOPT_WRITEDATA.

Set the userdata argument with the CURLOPT_WRITEDATA option.

The callback function will be passed as much data as possible in all invokes, but you cannot possibly make any assumptions. It may be one byte, it may be thousands. The maximum amount of body data that can be passed to the write callback is defined in the curl.h header file: CURL_MAX_WRITE_SIZE (the usual default is 16K). If you however have CURLOPT_HEADER set, which sends header data to the write callback, you can get up to CURL_MAX_HTTP_HEADER bytes of header data passed into it. This usually means 100K.

CURLOPT_WRITEDATA

Data pointer to pass to the file write function. If you use the CURLOPT_WRITEFUNCTION option, this is the pointer you‘ll get as input. If you don‘t use a callback, you must pass a ‘FILE *‘ (cast to ‘void *‘) as libcurl will pass this to fwrite() when writing data. By default, the value of this parameter is unspecified.

The internal CURLOPT_WRITEFUNCTION will write the data to the FILE * given with this option, or to stdout if this option hasn‘t been set.

If you‘re using libcurl as a win32 DLL, you MUST use the CURLOPT_WRITEFUNCTION if you set this option or you will experience crashes.

This option is also known with the older name CURLOPT_FILE, the name CURLOPT_WRITEDATA was introduced in 7.9.7.

2. 完整代码如下:

点击(此处)折叠或打开

  1. /*------------------------------------------------------------------------------------------
  2. 名称: http_sina_curl_callbak.c
  3. 功能: 利用libcurl的回调机制实现sina股票接口. http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
  4. http://hq.sinajs.cn/list=sz150013
  5. http://hq.sinajs.cn/list=sh601318
  6. #libcurl的调试信息
  7. * About to connect() to hq.sinajs.cn port 80 (#0)
  8. * Trying 219.142.78.242...
  9. * connected
  10. * Connected to hq.sinajs.cn (219.142.78.242) port 80 (#0)
  11. > GET /list=sz150001 HTTP/1.1
  12. Host: hq.sinajs.cn
  13. Accept: * *
  14. < HTTP/1.1 200 OK
  15. < Cache-Control: no-cache
  16. < Content-Length: 250
  17. < Connection: Keep-Alive
  18. < Content-Type: application/x-javascript; charset=GBK
  19. <
  20. * Connection #0 to host hq.sinajs.cn left intact
  21. * Closing connection #0
  22. #运行结果:
  23. [email protected]:/xutest# ./http_sina_stock
  24. sz150001: dq = 0.724, jg = 0.730, jd = 0.722, jk = 0.729
  25. sz150013: dq = 0.886, jg = 0.893, jd = 0.885, jk = 0.889
  26. sz150100: dq = 0.981, jg = 0.982, jd = 0.979, jk = 0.980
  27. sz150152: dq = 0.964, jg = 0.967, jd = 0.964, jk = 0.965
  28. sz150018: dq = 0.958, jg = 0.960, jd = 0.957, jk = 0.960
  29. [email protected]:/xutest#
  30. -------------------------------------------------------------------------------------------*/
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <curl/curl.h>
  35. #include <assert.h>
  36. #define HTTP_GET "GET"
  37. #define HTTP_PUT "PUT"
  38. #define HTTP_HEAD "HEAD"
  39. #define HTTP_POST "POST"
  40. #define HTTP_DELETE "DELETE"
  41. #define HTTP_RET_OK "HTTP/1.1 200 OK\r\n"
  42. #define SINA_HOST "hq.sinajs.cn"
  43. #define SINA_PORT 80
  44. #define ARRAY_COUNT(x) (sizeof(x) / sizeof(x[0]))
  45. typedef struct {
  46. float price_dq;    //当前价, 取拼音的首字母
  47. float price_zs;    //昨收价
  48. float price_jk;    //今开价
  49. float price_jg;    //今高价
  50. float price_jd;    //今低价
  51. } stock_info_t;
  52. #define DBG //printf
  53. #define CURL_DBG (0)    //1=开启curl的调试
  54. //-----------------------------------------------------------------------------------------
  55. static void delay_ms(int msec)
  56. {
  57. struct timeval timeout;
  58. memset(&timeout, 0, sizeof(struct timeval));
  59. timeout.tv_sec    = msec / 1000;
  60. timeout.tv_usec    = (msec % 1000) * 1000;
  61. select(0, NULL, NULL, NULL, &timeout);
  62. }
  63. size_t callback_get_head(void *ptr, size_t size, size_t nmemb, void *userp)
  64. {
  65. strcat(userp, ptr);
  66. return size * nmemb; //必须返回这个大小, 否则只回调一次
  67. }
  68. static char connect_cloud(char *pc_ret, const char *host_addr, const int portno,
  69. const char *pc_method, struct curl_slist *http_headers)
  70. {
  71. CURL *curl;
  72. CURLcode res = CURLE_GOT_NOTHING;
  73. assert((pc_ret != NULL) && (host_addr != NULL) && (pc_method != NULL));
  74. //curl_global_init(CURL_GLOBAL_DEFAULT);
  75. curl = curl_easy_init();
  76. if (!curl)    {
  77. fprintf(stderr, "--- curl init Error!\n");
  78. return 0;
  79. }
  80. curl_easy_setopt(curl, CURLOPT_URL, host_addr);
  81. curl_easy_setopt(curl, CURL_HTTP_VERSION_1_1, 1L);    //HTTP 1.1
  82. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);     //设置超时, 单位为秒.
  83. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);     //屏蔽其它信号, makes libcurl NOT ask the system to ignore SIGPIPE signals
  84. curl_easy_setopt(curl, CURLOPT_HEADER, 1L);         //下载数据包括HTTP头部, The default value for this parameter is 0.
  85. //curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);    //The default value for this parameter is 1
  86. #if (CURL_DBG == 1)
  87. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);    //调试用: 显示交互明细,
  88. //curl_easy_setopt(curl, CURLOPT_HEADER, 1L);    //调试用: 只显示头行的返回
  89. #endif
  90. #if 1
  91. curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, pc_method);
  92. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_get_head); //下载数据的回调函数
  93. curl_easy_setopt(curl, CURLOPT_WRITEDATA, pc_ret);                                //下载数据的指针
  94. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_headers);    //多行的HTTP头部
  95. #endif
  96. res = curl_easy_perform(curl);
  97. if(res != CURLE_OK)
  98. fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
  99. curl_easy_cleanup(curl);
  100. return 1;
  101. }
  102. int sina_get_stock(char *pc_ret, const char *pc_stockid)
  103. {
  104. char pc_url[200], ret;
  105. //组织请求头部, 自动末尾添加‘\r\n‘
  106. struct curl_slist *http_headers = NULL;
  107. http_headers = curl_slist_append(http_headers, "Accept: */*");
  108. //http_headers = curl_slist_append(http_headers, "Connection: Close");
  109. //发送请求, 再判断返回值
  110. //url = hq.sinajs.cn/list=sz150013
  111. sprintf(pc_url, "%s/list=%s", SINA_HOST, pc_stockid);
  112. ret = connect_cloud(pc_ret, pc_url, SINA_PORT, HTTP_GET, http_headers);
  113. //DBG("cloud ret = %s\n", pc_ret);
  114. //释放 http_headers资源
  115. curl_slist_free_all(http_headers);
  116. return(ret);
  117. }
  118. #if 0
  119. /*字符串不同含义的数据用逗号隔开了,按照程序员的思路,顺序号从0开始。
  120. 0:”大秦铁路”,股票名字;
  121. 1:”27.55″,今日开盘价;
  122. 2:”27.25″,昨日收盘价;
  123. 3:”26.91″,当前价格;
  124. 4:”27.55″,今日最高价;
  125. 5:”26.20″,今日最低价;
  126. 6:”26.91″,竞买价,即“买一”报价;
  127. 7:”26.92″,竞卖价,即“卖一”报价;
  128. 8:”22114263″,成交的股票数,由于股票交易以一百股为基本单位,所以在使用时,通常把该值除以一百;
  129. 9:”589824680″,成交金额,单位为“元”,为了一目了然,通常以“万元”为成交金额的单位,所以通常把该值除以一万;
  130. 10:”4695″,“买一”申请4695股,即47手;
  131. 11:”26.91″,“买一”报价;
  132. 12:”57590″,“买二”
  133. 13:”26.90″,“买二”
  134. 14:”14700″,“买三”
  135. 15:”26.89″,“买三”
  136. 16:”14300″,“买四”
  137. 17:”26.88″,“买四”
  138. 18:”15100″,“买五”
  139. 19:”26.87″,“买五”
  140. 20:”3100″,“卖一”申报3100股,即31手;
  141. 21:”26.92″,“卖一”报价
  142. (22, 23), (24, 25), (26,27), (28, 29)分别为“卖二”至“卖四的情况”
  143. 30:”2008-01-11″,日期;
  144. 31:”15:05:32″,时间;*/
  145. #endif
  146. void stock_parse(stock_info_t *stock, const char *pc_data)
  147. {
  148. char *pc_str, *pc_str1;
  149. int i;
  150. assert((stock != NULL) &&(pc_data != NULL));
  151. //DBG("data = %s\n", pc_data);
  152. pc_str = strstr(pc_data, HTTP_RET_OK);
  153. if (pc_str) {
  154. pc_str += strlen(HTTP_RET_OK);
  155. pc_str = strstr(pc_str, "\r\n\r\n");
  156. pc_str += 4;
  157. DBG("valid str = %s\n", pc_str);
  158. //解析数据, 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";
  159. pc_str = strchr(pc_str, ‘,‘);
  160. pc_str ++;
  161. for (i=0; i<5; i++) {
  162. pc_str1 = strchr(pc_str, ‘,‘);
  163. if (pc_str1) {
  164. *pc_str1 = ‘\0‘;
  165. switch(i) {
  166. case 0: stock->price_jk = atof(pc_str); break;    //今开
  167. case 1: stock->price_zs = atof(pc_str); break;    //昨收
  168. case 2: stock->price_dq = atof(pc_str); break;    //当前
  169. case 3: stock->price_jg = atof(pc_str); break;    //今高
  170. case 4: stock->price_jd = atof(pc_str); break;    //今低
  171. }
  172. pc_str = pc_str1 + 1;    //指向下个有效数据
  173. }
  174. else break;
  175. }
  176. }
  177. }
  178. //-------------------------------------------------------------------------------
  179. int main(void)
  180. {
  181. char pc_ret[1000];
  182. int i, max;
  183. stock_info_t stock;
  184. char *stock_array[] = {"sz150001", "sz150013", "sz150100", "sz150152", "sz150018"};    //改成自己的
  185. max = ARRAY_COUNT(stock_array);
  186. for(i=0; i<max; i++) {
  187. memset(pc_ret, 0x00, sizeof(pc_ret));
  188. sina_get_stock(pc_ret, stock_array[i]);
  189. DBG("sina ret OK = %s\n", pc_ret);
  190. stock_parse(&stock, pc_ret);
  191. printf("%s: dq = %.3f, jg = %.3f, jd = %.3f, jk = %.3f\n",
  192. stock_array[i], stock.price_dq, stock.price_jg, stock.price_jd ,stock.price_jk);
  193. }
  194. return 1;
  195. }

3. Makefile:

点击(此处)折叠或打开

  1. OPENWRT = 1
  2. ifeq ($(OPENWRT), 1)
  3. 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
  4. CFLAGS += -I ~/openwrt-lib/include -L ~/openwrt-lib/lib
  5. LFLAGS += -lcurl -lcrypto -lz -lssl
  6. else
  7. CC = gcc
  8. LFLAGS += -lcurl
  9. endif
  10. CFLAGS += -Wall -O2
  11. #CFLAGS += -g
  12. #可执行文件名和相关的obj文件
  13. APP_BINARY = http_sina_stock
  14. SRCS += http_sina_curl_callback.c
  15. OBJS = $(SRCS:.c=.o)
  16. all: APP_FILE
  17. APP_FILE: $(OBJS)
  18. $(CC) $(CFLAGS) $(OBJS) -o $(APP_BINARY) $(LFLAGS)
  19. .PHONY: clean
  20. clean:
  21. @echo "cleanning project"
  22. $(RM) *.a $(OBJS) *~ *.so *.lo $(APP_BINARY)
  23. @echo "clean completed"

4. openwrt下运行结果如下
[email protected]:/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

[email protected]:/xutest#

时间: 2024-10-09 13:02:57

(转)利用libcurl获取新浪股票接口, ubuntu和openwrt实验成功(三)的相关文章

js获取新浪天气接口

1 <!doctype html> 2 <html class="no-js fixed-layout"> 3 <head> 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <title>天气</title> 7 </he

【php】利用新浪api接口与php获取远程数据的方法,获取IP地址,并获取相应的IP归属地

本文与<[Servlet]Javaweb中,利用新浪api接口,获取IP地址,并获取相应的IP归属地>(点击打开链接)为姊妹篇,只是后端编程语言换成了php. 做出同样的效果,打开页面,得到客户端的ip,并获取利用新浪api接口获取此ip的归属地. 可以看到,在IE6也是相当正常的. 目录结构如下,非常简单,同样就两个文件,其实如果你愿意,写成一个php文件也可以,但是显示层和逻辑业务层还是不混在一起为好吧? 唯一值得注意的是,这两个文件打死也不能一个叫ipGet.php,ipGet.html

【Servlet】Javaweb中,利用新浪api接口,获取IP地址,并获取相应的IP归属地

这里之所以调用新浪api接口,主要是可以避免我们在本地存放一个ip归属地库, 同时,我们在本地要存放用户的ip,仅仅存放其ip就可以了,无须存放其归属地,节省一个字段. 如下图,写一个带有获取客户端IP地址的网页: 首先,在Eclipse的目录结构如下: 里面除了servlet的支持包之外,就一个.jsp与一个.java. 其中这里用到Servlet3.0,因此web.xml没有任何东西: <?xml version="1.0" encoding="UTF-8"

新浪股票数据接口

股票数据的获取目前有如下两种方法可以获取:1. http/javascript接口取数据2. web-service接口1.http/javascript接口取数据1.1Sina股票数据接口以大秦铁路(股票代码:601006)为例,如果要获取它的最新行情,只需访问新浪的股票数据接口:http://hq.sinajs.cn/list=sh601006这个url会返回一串文本,例如:var hq_str_sh601006="大秦铁路, 27.55, 27.25, 26.91, 27.55, 26.2

Python如何调用新浪api接口的问题

前言:这些天在研究如何调用新浪开放平台的api分析新浪微博用户的数据 成果:成功调用了新浪api获取了用户的一些个人信息和无数条公共微博 不足:新浪开放平台访问有限制,返回的数据着实有限,不足以分析问题,真的要分析问题还是得个人写爬虫 下面是调用新浪开放api的过程: 第一步:按这个做就行 http://www.cnblogs.com/dhsunny/p/3578399.html?utm_source=tuicool&utm_medium=referral 其中有一不那个新浪api测试工具是打不

[iOS微博项目 - 2.1] - 获得新浪授权接口

A.如何获得新浪的授权接口 登陆新浪的开放平台 注册新浪账号 创建应用 获得应用id和请求地址 查阅相关API 关联需要进行测试的账号 1.登陆开放平台 http://open.weibo.com 2.注册账号 (略) 3.创建应用 4.填写开发者资料 5.创建应用 5.取得应用的App Key和App Secret B.新浪微博API 1.OAuth授权API 上面的redirect_uri也是必填参数,需要在"我的应用"管理页中填写 随便填一个就可以了,其实就是授权成功或者失败的跳

新浪支付接口对接的总结

最近公司用户了新浪支付,账户托管,写的过程中发现有问题的话百度很少就记录下自己疑惑的地方 1.接口介入方式 这种接口介入的方式,各大平台都差不多的,支付宝啊,微信支付啊,融宝支付啊,银盈通啊.都是系统必要的参数,和接口需要的参数,拼一起然互加密. 新浪支付生成 sign 的方式,签名的方式可以是 RSA 的加密方式和 MD5 的加密的方式,不过新浪推荐的是MD5的加密方式,但是给的demo里面是RSA的方式,所有自己用的 也会是RSA的加密方式. 简单的例子   创建激活会员 public st

【API】新浪天气接口 Beta

新浪天氣接口那是公認的好,可是百度之後發現很簡陋,所以自己寫了工具類,此處幫忙測試下其中的天氣接口,看有哪些地方要改進的. Jar 名称:          NonentityUtil Class 名称:       SinaWeatherUtil,新浪天氣 Util 類 方法名:            getWeatherByCity(String city,int forecastDays),根據城市獲取天氣 輸入參數:         city,城市,拼音或者漢語([BUG]輸入拼音返回的

如何利用php+android+新浪sae服务器做一个app下载应用

功能简介:提供一个app下载的平台,类似于appstore,上面有很多app可供下载 实现基本思路:利用android,在手机桌面建立一个图标,点击该图标不是打开app应用,而是跳转到一个web页面,这个web页面是部署在新浪sae服务器上面的,apk资源也是存放到新浪sae服                     务器上,本例子使用的web变成语言主要是利用smarty模板php编写的 首先是android页面,就一个简单的url跳转,把跳转到activity换成跳转到web页面,代码如下