ror: " . $error, 'http_code' => 0, ]; } // 获取HTTP状态码 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // 返回响应和HTTP状态码 return [ 'response' => $response, 'http_code' => $httpCode, ]; } // 公共函数,用于设置缓存目录和文件名 function setupCache($subDir) { // 设置时区为上海 date_default_timezone_set('Asia/Shanghai'); // 获取当前日期,格式为 YYYYMMDD $currentDate = date('Ymd'); // 获取当前时间(小时) 24小时制 $currentHour = (int) date('H'); // 缓存目录 $cacheDir = ROOT_PATH . 'api'; // 创建缓存目录,如果它不存在的话 if (!file_exists($cacheDir)) { mkdir($cacheDir, 0755, true); } // 子目录sina $jsonDataDir = $cacheDir . '/' . $subDir; // 创建sina目录,如果它不存在的话 if (!file_exists($jsonDataDir)) { mkdir($jsonDataDir, 0755, true); } // 缓存文件名,使用当前日期作为文件名 $cacheFile = $jsonDataDir . '/' . $currentDate . '.json'; // 默认缓存时间为2小时 $cacheTime = 7200; // 返回缓存文件路径和缓存时间 return [ 'cacheDir' => $cacheDir, 'cacheFile' => $cacheFile, 'cacheTime' => $cacheTime, // 返回计算后的缓存时间 'currentDate' => $currentDate, // 返回当前日期 'currentHour' => $currentHour, // 返回当前小时 ]; } // 使用cURL或fopen来检查URL是否存在,中英语重定向使用 function urlExists($url) { // 使用cURL来检查URL是否存在 $ch = curl_init($url); curl_setopt($ch, CURLOPT_NOBODY, true); // 不需要获取页面内容 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 允许重定向 curl_setopt($ch, CURLOPT_HEADER, true); // true获取HTTP头 curl_exec($ch); // 执行cURL请求 $retCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 获取HTTP状态码 curl_close($ch); // 关闭cURL会话 // 如果状态码是200,表示页面存在 return $retCode == 200; } // 随机代理IP 使用代理可能影响速度 // 芝麻代理$apiUrl = "https://www.xiequ.cn/index.html?a6fd6043"; function setRandomProxy(&$ch, $apiUrl) { // 初始化cURL会话 curl_setopt($ch, CURLOPT_URL, $apiUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 执行cURL请求并获取代理列表 $proxyList = curl_exec($ch); if ($proxyList === false) { // 错误处理,例如记录日志或者抛出异常 error_log('CURL error: ' . curl_error($ch)); return false; } // 将代理列表分割成数组 $proxies = explode("\n", trim($proxyList)); // 使用trim去除可能的空白字符 // 检查是否有可用的代理 if (count($proxies) === 0) { // 错误处理,例如记录日志或者抛出异常 error_log('No proxies found in the response.'); return false; } // 随机选择一个代理 $proxy = $proxies[array_rand($proxies)]; // 解析代理IP和端口 $proxyParts = explode(':', $proxy); if (count($proxyParts) !== 2) { // 错误处理,如果代理格式不正确 error_log('Invalid proxy format: ' . $proxy); return false; } list($proxyIp, $proxyPort) = $proxyParts; // 设置代理 curl_setopt($ch, CURLOPT_PROXY, $proxyIp); // 设置代理IP curl_setopt($ch, CURLOPT_PROXYPORT, (int) $proxyPort); // 设置代理端口,并确保端口是整数类型 // 确保getRandUA函数存在并且返回有效的用户代理 if (function_exists('getRandUA')) { curl_setopt($ch, CURLOPT_USERAGENT, getRandUA()); } else { // 错误处理,如果getRandUA函数不存在 error_log('Function getRandUA does not exist.'); return false; } return true; } // 随机UserAgent设置HTTP请求头模拟来自不同客户端的请求 function getUserAgents() { return [ // 百度蜘蛛 'Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)', // 谷歌蜘蛛 'Googlebot/2.1 (+http://www.google.com/bot.html)', // 必应蜘蛛 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)', // 神马蜘蛛 'Mozilla/5.0 (compatible; SmappBot/1.0; +http://www.smapp.com/bot)', // 俄罗斯搜索引擎Yandex蜘蛛 'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)', // 腾讯SOSO蜘蛛 'Mozilla/5.0 (compatible; Sosospider/2.0; +http://help.soso.com/webspider.htm)', // 其他爬虫和蜘蛛 'Mozilla/5.0 (compatible; DuckDuckBot-Https/1.1; https://duckduckgo.com/duckduckbot)', 'Mozilla/5.0 (compatible; MJ12bot/v1.4.5; http://www.majestic12.co.uk/bot.php?+)', 'Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)', 'Mozilla/5.0 (compatible; Facebot; +http://www.facebot.com/facebot.html)', 'Mozilla/5.0 (compatible; DotBot/1.1; http://www.opensiteexplorer.org/dotbot, help@moz.com)', 'Mozilla/5.0 (compatible; BLEXBot/1.0; +http://webmeup-crawler.com/)', 'Mozilla/5.0 (compatible; Yeti/1.0; +http://naver.me/bot)', // 常用浏览器用户代理 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36', 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1', 'Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36', 'Mozilla/5.0 (Linux; Android 10; LYA-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 HuaweiBrowser/11.0.2.302 Mobile Safari/537.36', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0', 'Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1', 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LG-V410/V41020d Build/KOT49I.V41020d) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.1599.103 Safari/537.36', // 更多设备和浏览器 // ... 你可以继续添加更多的用户代理字符串 ]; } // 随机选择一个用户代理 function getRandUA() { $userAgents = getUserAgents(); // 获取用户代理数组 return $userAgents[array_rand($userAgents)]; // 随机选择一个用户代理 } /** * **************************************************************************** * * Jijinhao金融报价 * **************************************************************************** **/ /** * 格式化数字,保留2位小数,并去掉末尾的0(如果小数点后全是0,则去掉小数点) * 例如: * - 986.00 → 986 * - 123.40 → 123.4 * - 100.00 → 100 * - 0.50 → 0.5 */ function formatDecimal($number) { $formatted = number_format($number, 2, '.', ''); // 去掉末尾的0,如果小数点后全是0,则去掉小数点 $formatted = preg_replace('/\.?0+$/', '', $formatted); return $formatted; } // curl_multi 进行并发获取数据保存JSON文件 14400秒请求一次,避免过于频繁请求被封 function getJijinhao($symbols, $cacheTime = 14400, $subDir = 'Jijinhao') { // 设置时区为上海 date_default_timezone_set('Asia/Shanghai'); // 插件目录 $cacheDir = ROOT_PATH . 'api'; // 确保ROOT_PATH是定义过的常量 $jsonDataDir = $cacheDir . '/' . $subDir; if (!file_exists($jsonDataDir)) { mkdir($jsonDataDir, 0755, true); } // 最大重试次数 $maxRetries = 3; // 初始化 curl_multi 句柄 $multiCurl = curl_multi_init(); $handles = []; $retrySymbols = []; // 遍历所有符号,为每个符号创建一个 cURL 句柄 foreach ($symbols as $symbol) { $cacheFile = $jsonDataDir . '/' . urlencode($symbol) . '.json'; // 检查缓存文件是否存在且未过期 if (file_exists($cacheFile) && time() - filemtime($cacheFile) < $cacheTime) { continue; // 跳过已缓存的符号 } // 初始化cURL会话 $ch = curl_init(); $convertersurl = 'https://api.jijinhao.com/sQuoteCenter/realTime.htm?code=' . urlencode($symbol); curl_setopt($ch, CURLOPT_URL, $convertersurl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_USERAGENT, getRandUA()); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept-Charset: utf-8', "Referer: https://www.cngold.org"]); // 将 cURL 句柄添加到 curl_multi 句柄中 curl_multi_add_handle($multiCurl, $ch); $handles[$symbol] = $ch; } // 执行批量请求 $running = null; do { curl_multi_exec($multiCurl, $running); } while ($running); // 处理每个请求的结果 foreach ($handles as $symbol => $ch) { $html = curl_multi_getcontent($ch); if (curl_errno($ch)) { $error_number = curl_errno($ch); $error_message = curl_error($ch); error_log("cURL错误 {$error_number}: {$error_message} 品种 {$symbol}"); $retrySymbols[] = $symbol; // 记录需要重试的符号 } else { // 解析 hq_str 字符串 $values = explode(',', $html); if (count($values) < 39) { error_log("收到的符号数据不足 {$symbol}"); $retrySymbols[] = $symbol; // 记录需要重试的符号 } else { $finalData = [ "website" => "https://www.toolcms.com", "author" => "Jason", "qq" => "1102264200", $symbol . 'lastPrice' => formatDecimal($values[3]), // 索引3 $symbol . 'openPrice' => formatDecimal($values[38]), // 索引38 $symbol . 'highPrice' => formatDecimal($values[4]), // 索引4 $symbol . 'lowPrice' => formatDecimal($values[5]), // 索引5 $symbol . 'closePrice' => formatDecimal($values[2]), // 索引2 $symbol . 'creatTime' => time(), // 当前时间 ]; // 计算 swingValue 和 swingRangeValue $swingValue = $finalData[$symbol . 'lastPrice'] - $finalData[$symbol . 'closePrice']; $swingRangeValue = ($swingValue / $finalData[$symbol . 'closePrice']) * 100; $finalData[$symbol . 'swingValue'] = round($swingValue, 2); $finalData[$symbol . 'swingRangeValue'] = round($swingRangeValue, 2); // 检查 lastPrice 是否为0或空 if (empty($finalData[$symbol . 'lastPrice']) || $finalData[$symbol . 'lastPrice'] == 0) { error_log("符号{$symbol}的lastPrice为空或为零,未写入缓存文件."); $retrySymbols[] = $symbol; // 记录需要重试的符号 } else { // 将数组转换为JSON格式字符串并写入文件 $cacheFile = $jsonDataDir . '/' . urlencode($symbol) . '.json'; $result = file_put_contents($cacheFile, json_encode($finalData, JSON_UNESCAPED_UNICODE)); if ($result === false) { error_log("写入缓存文件失败: " . $cacheFile); $retrySymbols[] = $symbol; // 记录需要重试的符号 } } } } // 关闭 cURL 句柄 curl_multi_remove_handle($multiCurl, $ch); curl_close($ch); } // 关闭 curl_multi 句柄 curl_multi_close($multiCurl); // 重试失败的请求 if (!empty($retrySymbols)) { $retries = 0; while ($retries < $maxRetries && !empty($retrySymbols)) { $multiCurl = curl_multi_init(); $handles = []; $newRetrySymbols = []; foreach ($retrySymbols as $symbol) { $cacheFile = $jsonDataDir . '/' . urlencode($symbol) . '.json'; // 初始化cURL会话 $ch = curl_init(); $convertersurl = 'https://api.jijinhao.com/sQuoteCenter/realTime.htm?code=' . urlencode($symbol); curl_setopt($ch, CURLOPT_URL, $convertersurl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_USERAGENT, getRandUA()); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept-Charset: utf-8', "Referer: https://www.cngold.org"]); // 将 cURL 句柄添加到 curl_multi 句柄中 curl_multi_add_handle($multiCurl, $ch); $handles[$symbol] = $ch; } // 执行批量请求 $running = null; do { curl_multi_exec($multiCurl, $running); } while ($running); // 处理每个请求的结果 foreach ($handles as $symbol => $ch) { $html = curl_multi_getcontent($ch); if (curl_errno($ch)) { $error_number = curl_errno($ch); $error_message = curl_error($ch); error_log("cURL错误 {$error_number}: {$error_message} 品种 {$symbol}"); $newRetrySymbols[] = $symbol; // 记录需要重试的符号 } else { // 解析 hq_str 字符串 $values = explode(',', $html); if (count($values) < 39) { error_log("收到的符号数据不足 {$symbol}"); $newRetrySymbols[] = $symbol; // 记录需要重试的符号 } else { $finalData = [ "website" => "https://www.toolcms.com", "author" => "Jason", "qq" => "1102264200", $symbol . 'lastPrice' => formatDecimal($values[3]), // 索引3 $symbol . 'openPrice' => formatDecimal($values[38]), // 索引38 $symbol . 'highPrice' => formatDecimal($values[4]), // 索引4 $symbol . 'lowPrice' => formatDecimal($values[5]), // 索引5 $symbol . 'closePrice' => formatDecimal($values[2]), // 索引2 $symbol . 'creatTime' => time(), // 当前时间 ]; // 计算 swingValue 和 swingRangeValue $swingValue = $finalData[$symbol . 'lastPrice'] - $finalData[$symbol . 'closePrice']; $swingRangeValue = ($swingValue / $finalData[$symbol . 'closePrice']) * 100; $finalData[$symbol . 'swingValue'] = round($swingValue, 2); $finalData[$symbol . 'swingRangeValue'] = round($swingRangeValue, 2); // 检查 lastPrice 是否为0或空 if (empty($finalData[$symbol . 'lastPrice']) || $finalData[$symbol . 'lastPrice'] == 0) { error_log("符号{$symbol}的lastPrice为空或为零,未写入缓存文件."); $newRetrySymbols[] = $symbol; // 记录需要重试的符号 } else { // 将数组转换为JSON格式字符串并写入文件 $cacheFile = $jsonDataDir . '/' . urlencode($symbol) . '.json'; $result = file_put_contents($cacheFile, json_encode($finalData, JSON_UNESCAPED_UNICODE)); if ($result === false) { error_log("写入缓存文件失败: " . $cacheFile); $newRetrySymbols[] = $symbol; // 记录需要重试的符号 } } } } // 关闭 cURL 句柄 curl_multi_remove_handle($multiCurl, $ch); curl_close($ch); } // 关闭 curl_multi 句柄 curl_multi_close($multiCurl); // 更新重试符号列表 $retrySymbols = $newRetrySymbols; $retries++; // 如果还未成功,等待一段时间再重试 if (!empty($retrySymbols) && $retries < $maxRetries) { sleep(2); // 等待2秒再重试 } } } return 'success'; } // Jijinhao 解码输出数据 function JijinhaoPrice($symbols) { $results = []; foreach ($symbols as $symbol) { $cacheFile = ROOT_PATH . 'api/Jijinhao/' . urlencode($symbol) . '.json'; if (file_exists($cacheFile)) { $json = file_get_contents($cacheFile); $data = json_decode($json, true); if (json_last_error() !== JSON_ERROR_NONE) { error_log("JSON解码错误: " . json_last_error_msg() . " 品种 {$symbol}"); $results[$symbol] = ['error' => 'JSON解码错误: ' . json_last_error_msg()]; continue; } // 初始化价格数组 $prices = []; // 检查 creatTime 是否存在 $creatTimeKey = $symbol . 'creatTime'; if (isset($data[$creatTimeKey]) && !empty($data[$creatTimeKey])) { // 动态构建键名并赋值 foreach (['lastPrice', 'openPrice', 'highPrice', 'closePrice', 'lowPrice'] as $key) { $prices[$key] = $data[$symbol . $key] ?? null; } $prices['creatTime'] = date('H:i:s', $data[$creatTimeKey]); } else { error_log("符号{$symbol}的“creatTime”缺失或为空"); $results[$symbol] = ['error' => "符号{$symbol}的“creatTime”缺失或为空"]; continue; } $results[$symbol] = $prices; } else { $results[$symbol] = ['error' => '缓存文件不存在']; } } return $results; } // Jijinhao 历史收盘价数据 // curl_multi 进行并发获取数据保存JSON文件 14400秒请求一次,避免过于频繁请求被封 function JijinhaoHistorys($symbols, $cacheTime = 14400, $subDir = 'JijinhaoHistorys', $chartdays = 900) { // 设置时区为上海 date_default_timezone_set('Asia/Shanghai'); // 插件目录 $cacheDir = ROOT_PATH . 'api'; $jsonDataDir = $cacheDir . '/' . $subDir; if (!file_exists($jsonDataDir)) { mkdir($jsonDataDir, 0755, true); } // 最大重试次数 $maxRetries = 3; $multiCurl = curl_multi_init(); $handles = []; $retrySymbols = []; // 遍历所有符号,为每个符号创建一个 cURL 句柄 foreach ($symbols as $symbol => $code) { $cacheFile = $jsonDataDir . '/' . urlencode($code) . '.json'; // 检查缓存文件是否存在且未过期 if (file_exists($cacheFile) && time() - filemtime($cacheFile) < $cacheTime) { continue; } // 初始化cURL会话 $ch = curl_init(); $apiUrl = 'https://api.jijinhao.com/quoteCenter/historys.htm?codes=' . urlencode($code) . '&style=3&pageSize='. $chartdays; curl_setopt_array($ch, [ CURLOPT_URL => $apiUrl, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_USERAGENT => getRandUA(), CURLOPT_HTTPHEADER => ['Accept-Charset: utf-8', "Referer: https://www.cngold.org"], CURLOPT_TIMEOUT => 30, ]); // 将 cURL 句柄添加到 curl_multi 句柄中 curl_multi_add_handle($multiCurl, $ch); $handles[$code] = [ 'handle' => $ch, 'symbol' => $symbol, 'cacheFile' => $cacheFile, ]; } // 执行批量请求 $running = null; do { curl_multi_exec($multiCurl, $running); } while ($running); // 处理每个请求的结果 foreach ($handles as $code => $item) { $ch = $item['handle']; $symbol = $item['symbol']; $cacheFile = $item['cacheFile']; $response = curl_multi_getcontent($ch); if (curl_errno($ch)) { $error_number = curl_errno($ch); $error_message = curl_error($ch); error_log("cURL错误 {$error_number}: {$error_message} 品种 {$symbol}({$code})"); $retrySymbols[$code] = $symbol; } else { try { // 处理API返回的JavaScript变量格式 $response = preg_replace('/^var quote_json = /', '', $response); $response = preg_replace('/;$/', '', $response); $data = json_decode($response, true); if (!$data || !isset($data['data']) || !isset($data['data'][$code])) { throw new Exception("Invalid API response format for {$symbol}({$code})"); } $historyData = $data['data'][$code]; $result = []; // 提取q2和time并构建结果数组 foreach ($historyData as $item) { if (isset($item['q2']) && isset($item['time'])) { $result[] = [$item['time'], $item['q2']]; } } // 按时间降序排序(最新的在前) usort($result, function ($a, $b) { return $b[0] - $a[0]; }); // 准备最终数据 $finalData = [ "website" => "https://www.toolcms.com", "author" => "Jason", "qq" => "1102264200", "symbol" => $symbol, "code" => $code, "data" => $result, "updateTime" => time(), ]; // 写入文件(格式化) //$writeResult = file_put_contents($cacheFile, json_encode($finalData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); // 紧凑格式: $writeResult = file_put_contents($cacheFile, json_encode($finalData, JSON_UNESCAPED_UNICODE)); if ($writeResult === false) { throw new Exception("Failed to write cache file for {$symbol}({$code})"); } } catch (Exception $e) { error_log($e->getMessage()); $retrySymbols[$code] = $symbol; } } // 关闭 cURL 句柄 curl_multi_remove_handle($multiCurl, $ch); curl_close($ch); } // 关闭 curl_multi 句柄 curl_multi_close($multiCurl); // 重试失败的请求 if (!empty($retrySymbols) && $maxRetries > 0) { sleep(2); // 等待2秒再重试 $retryResult = JijinhaoHistorys($retrySymbols, $cacheTime, $subDir); if ($retryResult === 'success') { return 'success'; } else { return 'partial_failure'; // 部分数据获取失败 } } return empty($retrySymbols) ? 'success' : 'partial_failure'; } // Jijinhao 历史K线 // curl_multi 进行并发获取数据保存JSON文件 14400秒请求一次,避免过于频繁请求被封 function JijinhaoHistorysK($symbols, $cacheTime = 14400, $subDir = 'JijinhaoHistorysK', $chartdays = 900) { // 设置时区为上海 date_default_timezone_set('Asia/Shanghai'); // 插件目录 $cacheDir = ROOT_PATH . 'api'; $jsonDataDir = $cacheDir . '/' . $subDir; if (!file_exists($jsonDataDir)) { mkdir($jsonDataDir, 0755, true); } // 最大重试次数 $maxRetries = 3; $multiCurl = curl_multi_init(); $handles = []; $retrySymbols = []; // 遍历所有符号,为每个符号创建一个 cURL 句柄 foreach ($symbols as $symbol => $code) { $cacheFile = $jsonDataDir . '/' . urlencode($code) . '.json'; // 检查缓存文件是否存在且未过期 if (file_exists($cacheFile) && time() - filemtime($cacheFile) < $cacheTime) { continue; } // 初始化cURL会话 $ch = curl_init(); $apiUrl = 'https://api.jijinhao.com/quoteCenter/historys.htm?codes=' . urlencode($code) . '&style=3&pageSize=='. $chartdays; curl_setopt_array($ch, [ CURLOPT_URL => $apiUrl, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_USERAGENT => getRandUA(), CURLOPT_HTTPHEADER => ['Accept-Charset: utf-8', "Referer: https://www.cngold.org"], CURLOPT_TIMEOUT => 30, ]); // 将 cURL 句柄添加到 curl_multi 句柄中 curl_multi_add_handle($multiCurl, $ch); $handles[$code] = [ 'handle' => $ch, 'symbol' => $symbol, 'cacheFile' => $cacheFile, ]; } // 执行批量请求 $running = null; do { curl_multi_exec($multiCurl, $running); } while ($running); // 处理每个请求的结果 foreach ($handles as $code => $item) { $ch = $item['handle']; $symbol = $item['symbol']; $cacheFile = $item['cacheFile']; $response = curl_multi_getcontent($ch); if (curl_errno($ch)) { $error_number = curl_errno($ch); $error_message = curl_error($ch); error_log("cURL错误 {$error_number}: {$error_message} 品种 {$symbol}({$code})"); $retrySymbols[$code] = $symbol; } else { try { // 处理API返回的JavaScript变量格式 $response = preg_replace('/^var quote_json = /', '', $response); $response = preg_replace('/;$/', '', $response); $data = json_decode($response, true); if (!$data || !isset($data['data']) || !isset($data['data'][$code])) { throw new Exception("Invalid API response format for {$symbol}({$code})"); } $historyData = $data['data'][$code]; $result = []; // 提取q1(开盘价), q2(收盘价), q3(最高价), q4(最低价)和time并构建结果数组 foreach ($historyData as $item) { if (isset($item['q1']) && isset($item['q2']) && isset($item['q3']) && isset($item['q4']) && isset($item['time'])) { $result[] = [ $item['time'], // 时间戳 $item['q1'], // 开盘价 $item['q3'], // 最高价 $item['q4'], // 最低价 $item['q2'], // 收盘价 ]; } } // 按时间降序排序(最新的在前) usort($result, function ($a, $b) { return $b[0] - $a[0]; }); // 准备最终数据 $finalData = [ "website" => "https://www.toolcms.com", "author" => "Jason", "qq" => "1102264200", "symbol" => $symbol, "code" => $code, "data" => $result, "updateTime" => time(), ]; // 写入文件(紧凑格式) $writeResult = file_put_contents($cacheFile, json_encode($finalData, JSON_UNESCAPED_UNICODE)); if ($writeResult === false) { throw new Exception("Failed to write cache file for {$symbol}({$code})"); } } catch (Exception $e) { error_log($e->getMessage()); $retrySymbols[$code] = $symbol; } } // 关闭 cURL 句柄 curl_multi_remove_handle($multiCurl, $ch); curl_close($ch); } // 关闭 curl_multi 句柄 curl_multi_close($multiCurl); // 重试失败的请求 if (!empty($retrySymbols) && $maxRetries > 0) { sleep(2); // 等待2秒再重试 $retryResult = JijinhaoHistorysK($retrySymbols, $cacheTime, $subDir); if ($retryResult === 'success') { return 'success'; } else { return 'partial_failure'; // 部分数据获取失败 } } return empty($retrySymbols) ? 'success' : 'partial_failure'; } /** * **************************************************************************** * * END * **************************************************************************** **/ } ?> Toolcms 5.0.1 错误

错误信息

错误位置

基本信息

程序流程

SQL

$_GET

$_POST

$_COOKIE

包含文件

其他信息