获取中国银行和新浪汇率

白与黑 2023-10-31 16:40:00 460℃ 11131 0条

中国银行汇率查询:https://srh.bankofchina.com/search/whpj/search_cn.jsp

1.参数:

字段描述
nothing开始日期,例如2023-10-23
erectDate结束日期,例如2023-10-25
pjname币种名称,例如“欧元”
page页码,默认1

2.封装类

<?php
class BocRate {
    private        $settings    = array(
                                    'used'            => true,
                                    'url'            => 'https://srh.bankofchina.com/search/whpj/search_cn.jsp',
                                    'post_string'    => 'nothing=%s&erectDate=%s&pjname=%s&page=%s',
                                    'money_code'    => array('EUR' => '1326', 'USD' => '1316', 'GBP' => '1314','HKD' => '1315','RUB' => '1843','BRL' => '3253'),
                                    'money_name'    => array('EUR'=>'欧元', 'USD'=>'美元', 'GBP'=>'英镑','HKD'=>'港币','RUB'=>'卢布','BRL'=>'巴西里亚尔'),
                                    'count_preg'    => '/var m_nRecordCount = (.*);/',
                                    'size_preg'        => '/var m_nPageSize = (.*);/',
                                    'table_preg'    => '/<table cellpadding="0" cellspacing="0" width="100%" align="left">
            <tr>
([\s\S]*?)<\/table>/',    //别乱排版,不然会匹配不到
                                    'table_header'    => array('货币名称', '现汇买入价', '现钞买入价', '现汇卖出价', '现钞卖出价', '中行折算价', '发布时间'),
                                    'header_var'    => array('currency', 'rate_po', 'rate_cash', 'rate_average', 'rate_norm',  'boc', 'pub_time'),
                                    'value_preg'    => '/<td>(.*?)<\/td>/s',
                                    'charset'        => 'GB2312'
                                );
    
    private function composeData($post_string, $rate_date, $pjname, $page=1) {
        return(sprintf($post_string, urlencode($rate_date), urlencode($rate_date), urlencode($pjname), urlencode($page)));
    }
    public function getBocRate(&$result,$rate_date, $from, $to='RMB') {
        $result['from']        = $from;
        $result['to']        = $to;
        $post_data   = $this->composeData($this->settings['post_string'], $rate_date, $this->settings['money_name'][$from]);
        $data        = $this->curlPost($this->settings['url'],$post_data);
        if (false === $data) { 
            $result['error'] = 'access webpage error, url=' . $this->settings['url'] . '<>post=' . $post_data;
            return(false);
        }
        $page_no = 1;
        $line_no = 1;
        if (preg_match($this->settings['count_preg'], $data, $record_count)) { //查找记录的总条数
            if (is_numeric($record_count[1]) && $record_count[1] > 0) { //是正数
                if (preg_match($this->settings['size_preg'], $data, $page_size)) { //查找每页的条数
                    if (is_numeric($page_size[1]) && ($page_size[1] > 0)) { //是正数
                        $page_no = intval(($record_count[1] - 1) / $page_size[1] + 1); //计算一共有多少页
                        $line_no = $record_count[1] - ($page_no - 1) * $page_size[1]; //最后一条所在的行数
                    }
                }
            }
        }
        if (1 != $page_no) { //要抓的汇率不在第一页
            $post_data = $this->composeData($this->settings['post_string'], $rate_date, $this->settings['money_name'][$from], $page_no);
            $data2        = $this->curlPost($this->settings['url'],$post_data);
            if ($data2) { //成功取到网页
                $data = $data2;
                unset($data2);
            }else {
                $line_no = 1; //没有抓到最后一页,那就还用抓到页的第一行
            }
        }
        if (!preg_match($this->settings['table_preg'], $data, $table)) { //未找到汇率表
            $result['error'] = 'cannot find table, source code=' . $data;
            return(false);
        }
        $rows = explode('</tr>', $table[1]); //对表格分行,只分到需要的行
        if (count($rows) < $line_no+1) { //行数不对
            $result['error'] = 'cannot find encough rows, source code=' . $table[1];
            return(false);
        }
        $table_header = $this->settings['table_header'];
        preg_match_all('/<th>(.*?)<\/th>/s',$rows[0], $head);
        $head = $head[1];
        $header_count = count($table_header);
        if (count($head)< $header_count) { //表头不对
            $result['error'] = 'table header error, source code=' . $rows[0];
            return(false);
        }
        for ($i=0; $i<$header_count; $i++) { //核对表头
            if (false === strpos($head[$i], $table_header[$i])) { //表头不匹配
                $result['error'] = 'table header error, source code=' . $rows[0];
                return(false);
            }
        }
        if (!preg_match_all($this->settings['value_preg'], $rows[$line_no], $columns)) { //行不匹配
            $result['error'] = 'column mismatch, source code=' . $rows[$line_no];
            return(false);
        }
        $columns = $columns[1];
        $count   = count($columns);
        if ($count < $header_count) { //抓取到的值少于表头的列数,出错
            $result['error'] = 'column mismatch, source code=' . $rows[$line_no];
            return(false);
        }
        for($i=0; $i<$header_count; $i++) {
            $result[$this->settings['header_var'][$i]] = trim($columns[$i]);
        }
        $money_name = $this->settings['money_name'][$from];
        if ($result['currency'] != $money_name) {//抓取到的币值名称不匹配
            $result['error'] = 'money name mismatch, ' . print_r($result, true);
            return false;
        }
        ///特殊处理BRL,
        if($money_name == '巴西里亚尔'){
            $result['rate_average'] = 0;
            $result['rate_po']      = trim($columns[5]);
        }        
        return true;
    }

    public function curlPost($url, $post = array(), $timeout = 60){
        if (empty($url)) {
            return '';
        }
        $ch            = curl_init(); //初始化
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);//只需要设置一个秒的数量就可以
        curl_setopt($ch, CURLOPT_POST, 1);
        if(is_array($post)){
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
        }else{
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        }
        if(stripos($url,'https') === 0){
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        }
        $response    = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}
?>

3.使用方式

require_once 'BocRate.php';
function getRate($from){
    $date = date("Y-m-d");
    $rate = new BocRate();
    $data = array();
    $rate->getBocRate($data,$date,$from,'RMB');
    return $data;
}

$money_name = array('EUR'=>'欧元', 'USD'=>'美元', 'GBP'=>'英镑', 'HKD'=>'港币','RUB'=>'卢布');
foreach ($money_name as $key=>$item) {
    $info = getRate($key);
    var_dump( $info);
}

4.效果

array(9) {
  ["from"] => string(3) "EUR"
  ["to"] => string(3) "RMB"
  ["currency"] => string(6) "欧元"
  ["rate_po"] => string(6) "774.43"
  ["rate_cash"] => string(6) "768.59"
  ["rate_average"] => string(6) "779.85"
  ["rate_norm"] => string(6) "781.87"
  ["boc"] => string(6) "761.98"
  ["pub_time"] => string(19) "2023.10.31 00:00:05"
}

新浪汇率查询:http://biz.finance.sina.com.cn/forex/forex.php?startdate=2023-10-31&enddate=2023-12-01&money_code=HKD&type=0

1.参数

字段描述
startdate开始日期,例如2023-10-23
enddate结束日期,例如2023-10-25
money_code币种,例如“EUR”
type页码,默认0

2.封装类

<?php

class SinaRate{
    
    private        $settings    = array(
                                    'url'            => 'http://biz.finance.sina.com.cn/forex/',
                                    'get_string'    => 'forex.php?startdate=%s&enddate=%s&money_code=%s&type=0',
                                    'money_code'    => array('EUR'=>'EUR', 'USD'=>'USD', 'GBP'=>'GBP','HKD'=>'HKD','RUB'=>'RUB'),
                                    'money_name'    => array('EUR'=>'欧元', 'USD'=>'美元', 'GBP'=>'英镑', 'HKD'=>'港币','RUB'=>'卢布'),
                                    'page_preg'        => "caption='%s兑人民币日线图'",
                                    'table_preg'    => '/<table class="list_table">([\s\S]*?)<\/table>/',
                                    'row_count'        => 2,
                                    'table_header'    => array('日期', '汇买价(元)', '钞买价(元)', '钞卖价/汇卖价', '中间价'),
                                    'header_var'    => array('pub_time', 'rate_po', 'rate_cash', 'rate_average', 'rate_convert'),
                                    'pub_time_index'=> 0,
                                    'value_preg'    => '/<tr >[\s\S]*?<td >(.*?)<\/td>[\s\S]*?<td >(.*?)<\/td>[\s\S]*?<td >(.*?)<\/td>[\s\S]*?<td >(.*?)<\/td>[\s\S]*?<td >(.*?)<\/td>/',
                                    'value_omit'    => array('rate_norm' => 'rate_average'),
                                    'charset'        => 'GB2312'
                                );
    private function composeData($get_string, $rate_date, $pjname) {
        return(sprintf($get_string, urlencode($rate_date), urlencode($rate_date), urlencode($this->settings['money_code'][$pjname])));
    }
    
    public function getSinaRate(&$result,$rate_date, $from, $to='RMB') {
        $result['from']        = $from;
        $result['to']        = $to;
        $result['source']    = $this->settings['class'];
        
        $get_data = $this->composeData($this->settings['get_string'], $rate_date, $from);
        $data = file_get_contents($this->settings['url'] . $get_data);

        if (false === $data) { 
            $result['error'] = 'access webpage error, url=' . $this->settings['url'] . $get_data;
            return(false);
        }

        $page_sign = sprintf($this->settings['page_preg'], $this->settings['money_name'][$from]);
        $page_sign = iconv('UTF-8', $this->settings['charset'], $page_sign);


        if (false === strpos($data, $page_sign)) { //页面不匹配
            $result['error'] = 'page mismatch, source code=' . $data;
            return(false);
        }

        if (!preg_match($this->settings['table_preg'], $data, $table)) { //未找到汇率表
            $result['error'] = 'cannot find table, source code=' . $data;
            return(false);
        }

        $rows = explode('</tr>', $table[1]); //对表格分行
        if (count($rows) != $this->settings['row_count']+1) { //表格的行数不对
            $result['error'] = 'wrong row count, source code=' . $table[1];
            return(false);
        }

        
        $table_header = $this->settings['table_header'];
        $head = explode('</td>', $rows[0]); //处理表头
        $header_count = count($table_header);
        if (count($head) < $header_count) { //表头不对
            $result['error'] = 'table header error, source code=' . $rows[0];
            return(false);
        }

        for ($i=0; $i<$header_count; $i++) { //核对表头
            if (false === strpos($head[$i], iconv('UTF-8', $this->settings['charset'], $table_header[$i]))) { //表头不匹配
                $result['error'] = 'table header error, source code=' . $rows[0];
                return(false);
            }
        }

        if (!preg_match_all($this->settings['value_preg'], $rows[1], $columns)) { //行不匹配
            $result['error'] = 'column mismatch, source code=' . $rows[1];
            return(false);
        }
        
        $count = count($columns);
        if ($count <= $header_count) { //抓取到的值少于表头的列数,出错
            $result['error'] = 'column mismatch, source code=' . $rows[$line_no];
            return(false);
        }
        
        for($i=1; $i<$header_count+1; $i++) {
            $result[$this->settings['header_var'][$i-1]] = $columns[$i][0];
        }

        if ($result['pub_time'] != $rate_date) { //日期不匹配
            $result['error'] = "date mismatch, wanted date: $rate_date, got date: " . $result['pub_time'];
            return(false);
        }
            
        $omits = $this->settings['value_omit'];
        foreach ($omits as $key => $value) {
            $result[$key] = $result[$value];
        }
        return(true);
    }
}

3.使用方式

require_once 'SinaRate.php';
function getRate($from){
    $date = date("Y-m-d");
    $rate = new SinaRate();
    $data = array();
    $rate->getSinaRate($data,$date,$from,'RMB');
    return $data;
}

$money_name = array('EUR'=>'欧元', 'USD'=>'美元', 'GBP'=>'英镑', 'HKD'=>'港币','RUB'=>'卢布');
foreach ($money_name as $key=>$item) {
    $info = getRate($key);
    var_dump($info);
}

4.效果

array(8) {
  ["from"] => string(3) "EUR"
  ["to"] => string(3) "RMB"
  ["pub_time"] => string(10) "2023-10-31"
  ["rate_po"] => string(8) "773.7800"
  ["rate_cash"] => string(8) "767.9500"
  ["rate_average"] => string(8) "779.2000"
  ["rate_convert"] => string(8) "764.8000"
  ["rate_norm"] => string(8) "779.2000"
}
标签: PHP, HTML, 解惑

非特殊说明,本博所有文章均为博主原创。

评论啦~