input_sina.class.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <?php
  2. class Input_sina
  3. {
  4. const INPUT_SINA_URL = "http://hq.sinajs.cn/list=";
  5. static public function add_day_k($code, $exchange)
  6. {
  7. $data = self::_parse_day_k_data($code,$exchange);
  8. return Day_k::add($data);
  9. }
  10. /***
  11. * @param $code
  12. * @param $date
  13. * @return mixed
  14. * 日k线表 day_k_******(每月存一张表,比如boniu_day_k_202011)
  15. * 抓取当天的数据,结合腾讯的接口,每4秒抓取一条数据
  16. *
  17. */
  18. static public function add_to_immediate_day_k($code, $exchange)
  19. {
  20. $data = self::_parse_day_k_data($code,$exchange);
  21. return Immediate_base::add($data);
  22. }
  23. private static function _parse_day_k_data($code,$exchange)
  24. {
  25. $stock_code = $exchange . $code;
  26. $url = self::INPUT_SINA_URL . $stock_code;
  27. $content3 = self::_render_k_day_curl_data($url);
  28. if (empty($content3)) {
  29. throw new Exception('抓取的数据不能为空', 102);
  30. }
  31. $data['timestamp'] = time();
  32. $data['date'] = (int)date("Ymd", time());
  33. $data['code'] = $code;//股票代码此时去掉sh,sz
  34. $data['name'] = $content3[0];
  35. $data['open_price'] = floatval($content3[1]);//开盘价
  36. $data['close_price'] = floatval($content3[3]);//3点之后的当前价格就是收盘价
  37. $data['highest_price'] = floatval($content3[4]);//今日最高价
  38. $data['lowest_price'] = floatval($content3[5]);//今日最低价
  39. $data['amount'] = floatval($content3[8]);//成交的股票数,以百为单位
  40. $data['value'] = floatval($content3[9]);//成交金额以万为单位
  41. $dataContent = self::_get_tecent_stock_data($code,$exchange);
  42. $data["increase_price"] = empty($content1["increase_price"]) ? 0 : $content1["increase_price"]; // 涨跌价
  43. $data["increase_ratio"] = empty($content1["increase_ratio"]) ? 0 : $content1["increase_ratio"];// 涨跌幅
  44. $data["turnover"] = empty($content1["turnover"]) ? 0 : $content1["turnover"];// 换手率
  45. $data["pe_ttm"] = empty($dataContent["pe_ttm"]) ? 0 : $dataContent["pe_ttm"];//pe_ttm市盈率
  46. $data["tradable_value"] = empty($dataContent["tradable_value"]) ? 0 : (int)($dataContent["tradable_value"] * 100000000);//流通市值
  47. $data["total_value"] = empty($dataContent["total_value"]) ? 0 : (int)($dataContent["total_value"] * 100000000);//总市值
  48. $data["pb"] = empty($dataContent["pb"]) ? 0 : $dataContent["pb"];//市净率
  49. $data["pe_dynamic"] = empty($dataContent["pe_dynamic"]) ? 0 : $dataContent["pe_dynamic"]; //动态市盈率
  50. $data["pe_static"] = empty($dataContent["pe_static"]) ? 0 : $dataContent["pe_static"];//静态市盈率
  51. return $data;
  52. }
  53. static private function _render_k_day_curl_data($url)
  54. {
  55. $content = self::curl_exec($url);
  56. $content2 = iconv("gbk", "utf-8", $content);//子串
  57. $content3 = substr($content2, stripos($content2, "=\"") + 2); //获取 var hq_str_sz000002="万 科A,30.780,30.800,30.510, ="之后部分
  58. $content4 = substr($content3, 0, strripos($content3, "\";")); //获取 万 科A,30.94,0.14,0.45,584039,178827"; ";之前部分
  59. $content5 = explode(",", $content4);//分割
  60. return $content5;
  61. }
  62. private static function _get_tecent_stock_data($code, $exchange)
  63. {
  64. $dataContent = Input_tencent_day_k::get_stock_data($code, $exchange);
  65. if (!empty($dataContent)) {
  66. return $dataContent;
  67. }else{
  68. return [];
  69. }
  70. }
  71. //获取index_day_k
  72. static public function getIndexDayK($indexList)
  73. {
  74. $url = self::INPUT_SINA_URL;
  75. $contentList = self::_render_index_k_day_curl_data($url, $indexList);
  76. foreach ($contentList as $key => $item) {
  77. $data['code'] = $item['code'];
  78. $data['date'] = ConverseDate($item[30]);
  79. $data['name'] = trim($item[0]);
  80. $data['increase_price'] = floatval($item[3] - $item[2]); //涨跌价
  81. $data['timestamp'] = strtotime($item[30]); //当天的0点时间戳
  82. $data['open_price'] = floatval($item[1]); //开盘价
  83. $data['close_price'] = floatval($item[3]); //当前价,15点之后就是收盘价
  84. $data['highest_price'] = floatval($item[4]); //最高价
  85. $data['lowest_price'] = floatval($item[5]); //最低价
  86. $data['amount'] = self::getAmountForIndexDayK($data['code'], (int)($item[8])); //成交量,以手为单位
  87. $data['value'] = (int)($item[9]); //成交金额,以万为单位
  88. $data['increase_ratio'] = 0; //涨跌幅
  89. if (!empty($data['open_price']))
  90. $data['increase_ratio'] = round($data['increase_price'] * 100 / $data['open_price'], 2);
  91. if (!empty($item[0])) { //判断非法股票代码
  92. Index_day_k::addOrUpdateByCodeDate($data);
  93. }
  94. }
  95. return;
  96. }
  97. //获取全部股票代码和名称列表
  98. static public function getAllStockCodeAndNameList()
  99. {
  100. //上证主板 60****
  101. for($i = 0; $i < 50; $i++) {
  102. $start = 600000 + $i * 200;
  103. self::getPartStockCodeAndNameList('sh', 10, $start, $start + 200);
  104. }
  105. //上证科创板 688***
  106. for($i = 0; $i < 5; $i++) {
  107. $start = 688000 + $i * 200;
  108. self::getPartStockCodeAndNameList('sh', 11, $start, $start + 200);
  109. }
  110. //深证主板 000000~001999
  111. for($i = 0; $i < 10; $i++) {
  112. $start = 0 + $i * 200;
  113. self::getPartStockCodeAndNameList('sz', 20, $start, $start + 200);
  114. }
  115. //深证中小板 002000~002999
  116. for($i = 0; $i < 5; $i++) {
  117. $start = 2000 + $i * 200;
  118. self::getPartStockCodeAndNameList('sz', 21, $start, $start + 200);
  119. }
  120. //深证创业板 300***
  121. for($i = 0; $i < 5; $i++) {
  122. $start = 300000 + $i * 200;
  123. self::getPartStockCodeAndNameList('sz', 22, $start, $start + 200);
  124. }
  125. return;
  126. }
  127. //获取指定条件的股票代码和名称列表
  128. static public function getAllIndexCodeAndNameList()
  129. {
  130. $i = 0;
  131. $index[$i]['code'] = '000001';
  132. $index[$i]['name'] = '上证指数';
  133. $index[$i]['exchange'] = STOCK_EXCHANGE_SH;
  134. $index[$i]['sector'] = STOCK_SECTOR_SH_MAIN;
  135. $i++;
  136. $index[$i]['code'] = '399001';
  137. $index[$i]['name'] = '深证成指';
  138. $index[$i]['exchange'] = STOCK_EXCHANGE_SZ;
  139. $index[$i]['sector'] = STOCK_SECTOR_SZ_MAIN;
  140. $i++;
  141. $index[$i]['code'] = '000016';
  142. $index[$i]['name'] = '上证50';
  143. $index[$i]['exchange'] = STOCK_EXCHANGE_SH;
  144. $index[$i]['sector'] = STOCK_SECTOR_SH_MAIN;
  145. $i++;
  146. $index[$i]['code'] = '399300';
  147. $index[$i]['name'] = '沪深300';
  148. $index[$i]['exchange'] = STOCK_EXCHANGE_SZ;
  149. $index[$i]['sector'] = STOCK_SECTOR_SZ_MAIN;
  150. $i++;
  151. $index[$i]['code'] = '399006';
  152. $index[$i]['name'] = '创业板指';
  153. $index[$i]['exchange'] = STOCK_EXCHANGE_SZ;
  154. $index[$i]['sector'] = STOCK_SECTOR_SZ_CHUANGYE;
  155. $i++;
  156. $index[$i]['code'] = '000688';
  157. $index[$i]['name'] = '科创50';
  158. $index[$i]['exchange'] = STOCK_EXCHANGE_SH;
  159. $index[$i]['sector'] = STOCK_SECTOR_SH_KECHUANG;
  160. foreach ($index as $key => $item) {
  161. if (!empty($item['code'])) { //判断非法股票代码
  162. Index::addOrUpdateByCode($item);
  163. }
  164. }
  165. return;
  166. }
  167. //获取指定条件的股票代码和名称列表
  168. static private function getPartStockCodeAndNameList($exchange, $sector, $start, $end)
  169. {
  170. $data['exchange'] = $exchange;
  171. $data['sector'] = $sector;
  172. $codeList = array();
  173. $codeIndex = 0;
  174. $url = self::INPUT_SINA_URL;
  175. for($code = $start;$code < $end; $code++){
  176. $codeStr = sprintf('%06s', $code);
  177. $url .= 's_'.$exchange.$codeStr.',';
  178. $codeList[$codeIndex] = $codeStr;
  179. $codeIndex++;
  180. }
  181. $contentList = self::_render_index_k_day_curl_data($url, $codeList);
  182. foreach ($contentList as $key => $item) {
  183. $data['code'] = $item['code'];
  184. $data['name'] = trim($item[0]);
  185. if (!empty($item[0])) { //判断非法股票代码
  186. Stock::addOrUpdateByCode($data);
  187. }
  188. }
  189. return;
  190. }
  191. static private function _render_index_k_day_curl_data($url,$indexList)
  192. {
  193. $content = self::curl_exec($url);
  194. $codeList = array();
  195. $codeIndex = 0;
  196. foreach ($indexList as $item) {
  197. $codeStr = sprintf('%06s', $item['code']);
  198. $url .= $item['exchange'].$codeStr.',';
  199. $codeList[$codeIndex] = $codeStr;
  200. $codeIndex++;
  201. }
  202. if (empty($codeList)) {
  203. return 0;
  204. }
  205. $content2 = iconv("gbk", "utf-8", $content);//子串
  206. $arr1 = explode(";", $content2);//按股票分割
  207. $arr2 = array();
  208. $index = 0;
  209. $codeIndex = 0;
  210. foreach ($arr1 as $key => $item) {
  211. $tempItem = substr($item, stripos($item, "=\"") + 2); //获取 var hq_str_sz000002="万 科A,30.780,30.800,30.510, ="之后部分
  212. $tempItem = substr($tempItem, 0, strripos($tempItem, "\"")); //获取 万 科A,30.94,0.14,0.45,584039,178827"; ";之前部分
  213. $tempItem = trim($tempItem);
  214. if (!empty($tempItem)) {
  215. $arr2[$index] = explode(",", $tempItem);//分割
  216. $arr2[$index]['code'] = $codeList[$codeIndex];
  217. $index++;
  218. }
  219. $codeIndex++;
  220. }
  221. return $arr2;
  222. }
  223. //深市返回的成交量以个为单位,需转换为以手为单位
  224. static private function getAmountForIndexDayK($code, $amount)
  225. {
  226. $newAmount = $amount;
  227. $index = Index::getInfoByCode($code);
  228. if ($index['exchange'] == STOCK_EXCHANGE_SZ) {
  229. $newAmount = round($amount / 100);
  230. }
  231. return $newAmount;
  232. }
  233. /****
  234. * @param $url
  235. * @return array|bool|string
  236. * 对curl_setopt进行封装,消除代码冗余
  237. */
  238. static private function curl_exec($url)
  239. {
  240. $curlHandle = curl_init();
  241. curl_setopt($curlHandle, CURLOPT_URL, $url);
  242. curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
  243. curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false);
  244. curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, false);
  245. curl_setopt($curlHandle, CURLOPT_TIMEOUT, 10);
  246. $content = curl_exec($curlHandle);
  247. curl_close($curlHandle);//防止中文乱码
  248. return $content;
  249. }
  250. }