Pārlūkot izejas kodu

[AI旅游] 博物馆数据采集

tangyuanwang 1 mēnesi atpakaļ
vecāks
revīzija
8a2626669c

+ 75 - 0
app/Http/Controllers/Api/Museum/Spot.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace App\Http\Controllers\Api\Museum;
+
+use App\Http\Controllers\Controller;
+use Illuminate\Http\Request;
+use App\Servers\Wenlv\MuseumServer;
+use App\Models\Api\Museum\Spot as SpotModel;
+use App\Models\Api\Museum\SpotTmp as SpotTmpModel;
+
+class Spot extends Controller
+{
+    /**
+     * 采集博物馆列表数据
+     * @author    唐远望
+     * @version   1.0
+     * @date      2026-04-02
+     */
+    public function collect_data(SpotTmpModel $SpotTmpModel)
+    {
+        $MuseumServer = new MuseumServer();
+        $page_data = $MuseumServer->getMuseumPageData();
+        $pages = $page_data['pages'];
+        if ($pages > 0) {
+            for ($page = 1; $page < $pages; $page++) {
+                //查询是否存在第一页数据
+                $page_data = $SpotTmpModel->where(['page' => $page])->first();
+                if ($page_data) {
+                    $museum_list = json_decode($page_data->data, true);
+                    $this->add_museum($museum_list);
+                    continue;
+                }
+                $list_data = $MuseumServer->getMuseumList($page);
+                $list = isset($list_data['rows']['records']) ? $list_data['rows']['records']:'';
+                if (!$list) continue;
+                $SpotTmpModel->insert(['page' => $page, 'data' => json_encode($list)]);
+            }
+        }
+        // 加载模板
+        return json_send(['code' => 'success', 'msg' => '获取成功', 'data' => '']);
+    }
+
+
+    /**
+     * 添加博物馆数据到数据库
+     * @author    唐远望
+     * @version   1.0
+     * @date      2026-04-02
+     */
+    public function add_museum($list)
+    {
+        $SpotModel = new SpotModel();
+        $museum_type_config = [
+            '文化文物系统国有博物馆' => '1',
+            '其他行业国有博物馆' => '2',
+            '非国有博物馆' => '3',
+        ];
+        foreach ($list as $key => $value) {
+            $insert_data['museum_type_id'] = isset($museum_type_config[$value['NB_BWGXZ_NAME']]) ? $museum_type_config[$value['NB_BWGXZ_NAME']] : '0';
+            $insert_data['museum_level'] = isset($value['NB_ZLDJ_NAME']) ? $value['NB_ZLDJ_NAME'] : '';
+            $insert_data['is_open'] = '0';
+            $insert_data['name'] = isset($value['NB_BWGMC']) ? $value['NB_BWGMC'] : '';
+            $insert_data['intro'] = isset($value['NB_BWGJJ']) ? $value['NB_BWGJJ'] : '';
+            $insert_data['province_name'] = isset($value['NB_S_NAME']) ? $value['NB_S_NAME'] : '';
+            $insert_data['city_name'] = isset($value['NB_X_NAME']) ? $value['NB_X_NAME'] : '';
+            $insert_data['district_name'] = '';
+            $insert_data['insert_time'] = time();
+            //查询是否存在博物馆
+            $museum_info = $SpotModel->where(['name' => $insert_data['name'], 'province_name' => $insert_data['province_name']])->first();
+            if (!$museum_info) {
+                $SpotModel->insert($insert_data);
+            }
+        }
+    }
+}

+ 24 - 0
app/Models/Api/Museum/Spot.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Models\Api\Museum;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 博物馆数据模型
+ * @author 唐远望
+ * @version 1.0
+ * @date 2026-04-03
+ */
+class Spot extends Model
+{
+    use HasFactory;
+    // 与模型关联的表名
+    protected $table = 'museum_spot';
+    // 是否主动维护时间戳
+    public $timestamps = false;
+    // 定义时间戳字段名
+    // const CREATED_AT = 'insert_time';
+    // const UPDATED_AT = 'update_time';
+}

+ 24 - 0
app/Models/Api/Museum/SpotTmp.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Models\Api\Museum;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 博物馆临时数据模型
+ * @author 唐远望
+ * @version 1.0
+ * @date 2026-04-03
+ */
+class SpotTmp extends Model
+{
+    use HasFactory;
+    // 与模型关联的表名
+    protected $table = 'museum_tmp';
+    // 是否主动维护时间戳
+    public $timestamps = false;
+    // 定义时间戳字段名
+    // const CREATED_AT = 'insert_time';
+    // const UPDATED_AT = 'update_time';
+}

+ 49 - 0
app/Models/Manager/ScenicSpot.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace App\Models\Manager;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 景区模型
+ */
+class ScenicSpot extends Model
+{
+    use HasFactory;
+
+    protected $table = 'scenic_spot';
+
+    public $timestamps = false;
+
+    protected $connection = 'mysql';
+
+    /**
+     * 添加数据
+     */
+    public function add($data)
+    {
+        $data['insert_time'] = time();
+        $data['update_time'] = time();
+        $id = $this->query()->insertGetId($data);
+        if (!$id) {
+            return 0;
+        }
+
+        return $id;
+    }
+
+    /**
+     * 更新数据
+     */
+    public function edit($id, $data)
+    {
+        $data['update_time'] = time();
+        $result = $this->query()->where([['id', '=', $id]])->update($data);
+        if (!$result) {
+            return 0;
+        }
+
+        return $id;
+    }
+}

+ 170 - 0
app/Servers/Wenlv/MuseumServer.php

@@ -0,0 +1,170 @@
+<?php
+
+namespace App\Servers\Wenlv;
+
+use \Exception;
+
+/**
+ * 获取博物馆信息API接口
+ * @author 唐远望
+ * @version 1.0
+ * @date 2026-01-06
+ */
+class MuseumServer
+{
+    private $header;
+    private $baseUrl = 'http://nb.ncha.gov.cn';
+
+    /**
+     * 构造函数
+     * @throws Exception 当API密钥未设置时抛出异常
+     * 
+     */
+    public function __construct()
+    {
+        $this->header = [
+            'content-type:application/json;charset=UTF-8',
+            'accept:*/*',
+            'accept-encoding:gzip, deflate',
+            'accept-language:zh-CN,zh;q=0.9,en;q=0.8',
+            'cookie:Hm_lvt_352975963075889e3e294c05c9b5b506=1775198593; HMACCOUNT=958D4906DE24C8E1; Hm_lpvt_352975963075889e3e294c05c9b5b506=1775203189; JSESSIONID=F3391B6142667B4DEE48F9FD47B90056',
+            'host:nb.ncha.gov.cn',
+            'proxy-connection:keep-alive',
+            'referer:http://nb.ncha.gov.cn/museum.html?page=1&nianfen=2024&level=%E4%BA%8C%E7%BA%A7&showModel=list&order=default',
+            'user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36',
+            'x-requested-with:XMLHttpRequest',
+        ];
+    }
+
+
+    /**
+     * 尝试将接口返回内容转成 UTF-8,避免 GBK/GB18030 导致的乱码
+     * @param string $str
+     * @return string
+     */
+    private function ensureUtf8($str)
+    {
+        if (!is_string($str) || $str === '') {
+            return $str;
+        }
+
+        // 强制检测:优先判断是否已经是 UTF-8
+        $enc = mb_detect_encoding($str, ['UTF-8', 'GB18030', 'GBK', 'GB2312'], true);
+        if ($enc && strtoupper($enc) !== 'UTF-8') {
+            return mb_convert_encoding($str, 'UTF-8', $enc);
+        }
+
+        // 如果明显出现替换字符(常见于编码不匹配),尝试兜底从 GB18030 转码
+        if (strpos($str, '�') !== false) {
+            $converted = @mb_convert_encoding($str, 'UTF-8', 'GB18030');
+            if (is_string($converted) && $converted !== '') {
+                return $converted;
+            }
+        }
+
+        return $str;
+    }
+
+    /**
+     * 博物馆分页数据
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-08
+     */
+    public function getMuseumPageData()
+    {
+        $url = $this->baseUrl . '/je/api/loadDataNBLNList?current=1&size=15&NB_ND=2024';
+        $response = self::curl_get($url, $this->header);
+        $response_data = json_decode($response, true);
+        if (isset($response_data['rows']) && !empty($response_data['rows'])) {
+            $page_data = [
+                'totle' => $response_data['rows']['total'],
+                'current' => $response_data['rows']['current'],
+                'pages' => $response_data['rows']['pages'],
+                'size' => $response_data['rows']['size'],
+            ];
+        } else {
+            $page_data = [
+                'totle' => 0,
+                'current' => 0,
+                'pages' => 0,
+                'size' => 0,
+            ];
+        }
+        return $page_data;
+    }
+
+    /**
+     * 博物馆数据信息列表
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-08
+     */
+    public function getMuseumList($page)
+    {
+        $url = $this->baseUrl . '/je/api/loadDataNBLNList?current='.$page.'&size=100&NB_ND=2024&NB_BWGXZ_NAME=&NB_ZLDJ_NAME=&NB_MFKF=&NB_S_NAME=&NB_SS_NAME=&NB_BWGMC=';
+        $response = self::curl_get($url, $this->header);
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 获取博物馆详情
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-08
+     */
+    public function getMuseumDetail($BWG_NB_ID)
+    {
+        $url = $this->baseUrl . '/je/api/loadDataNBLN?parameter={"current":1,"size":-1,"BWG_NB_ID":"' . $BWG_NB_ID . '"}';
+        $response = self::curl_get($url, $this->header);
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 发送http post请求
+     * @param string $url 请求地址
+     * @param array $headers 请求头
+     * @param json $postdata 请求数据
+     * @param array $options curl配置项
+     */
+    public static function curl_post($url = '', $headers = '', $postdata = '', $options = array())
+    {
+        $ch = curl_init($url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_POST, 1);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        curl_setopt($ch, CURLOPT_ENCODING, '');  // 添加这一行,让 cURL 自动处理压缩
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
+        if (!empty($headers)) {
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        }
+        if (!empty($options)) {
+            curl_setopt_array($ch, $options);
+        }
+        $data = curl_exec($ch);
+        return $data;
+    }
+
+    /**
+     * 发送http get请求
+     */
+    public static function curl_get($url = '', $headers = '', $options = array())
+    {
+        $ch = curl_init($url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        curl_setopt($ch, CURLOPT_ENCODING, '');  // 添加这一行,让 cURL 自动处理压缩
+        if (!empty($headers)) {
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        }
+        if (!empty($options)) {
+            curl_setopt_array($ch, $options);
+        }
+        $data = curl_exec($ch);
+        return $data;
+    }
+}

+ 203 - 0
app/Servers/Wenlv/ScenicArea.php

@@ -0,0 +1,203 @@
+<?php
+
+namespace App\Servers\Wenlv;
+
+use \Exception;
+
+/**
+ * 获取景点信息API接口
+ * @author 唐远望
+ * @version 1.0
+ * @date 2026-01-06
+ */
+class ScenicArea
+{
+    private $app_key;
+    private $app_id;
+    private $app_secret;
+    private $header;
+    private $baseUrl = 'https://jt-open-platform.jt-health.cn/management/api';
+
+    /**
+     * 构造函数
+     * @throws Exception 当API密钥未设置时抛出异常
+     * 
+     */
+    public function __construct()
+    {
+
+        $time_string = date('Y-m-d', time());
+        $this->header = [
+            'time_string:' . $time_string,
+        ];
+    }
+
+    /**
+     * 发送http post请求
+     * @param string $url 请求地址
+     * @param array $headers 请求头
+     * @param json $postdata 请求数据
+     * @param array $options curl配置项
+     */
+    public static function curl_post($url = '', $headers = '', $postdata = '', $options = array())
+    {
+        $ch = curl_init($url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_POST, 1);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
+        if (!empty($headers)) {
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        }
+        if (!empty($options)) {
+            curl_setopt_array($ch, $options);
+        }
+        $data = curl_exec($ch);
+        return $data;
+    }
+
+    /**
+     * 发送http get请求
+     */
+    public static function curl_get($url = '', $headers = '', $options = array())
+    {
+        $ch = curl_init($url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        if (!empty($headers)) {
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        }
+        if (!empty($options)) {
+            curl_setopt_array($ch, $options);
+        }
+        $data = curl_exec($ch);
+        return $data;
+    }
+
+
+    /**
+     * 提交设备采样数据接口
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-06
+     */
+    public function submitDeviceData($request_data)
+    {
+        $url = $this->baseUrl . '/report/submitReport';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 获取报告接口
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-06
+     */
+    public function getReport($request_data)
+    {
+        $url = $this->baseUrl . '/report/getReport';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 获取报告18大风险对应的商品推荐
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-06
+     */
+    public function getDeviceData($request_data)
+    {
+        $url = $this->baseUrl . '/report/getRiskCommodityList';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 体质卡兑换
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-06
+     */
+    public function exchangeHealthCard($request_data)
+    {
+        $url = $this->baseUrl . '/physiqueCard/exchangePhysiqueCard';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 获取近两天报告
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-06
+     */
+    public function getTwoDayReport($request_data)
+    {
+        $url = $this->baseUrl . '/report/getDaysReportsList';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 获取近一周报告
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-06
+     */
+    public function getOneWeekReport($request_data)
+    {
+        $url = $this->baseUrl . '/report/getWeeksReportsList';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 两笔报告对比
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-06
+     */
+    public function compareTwoReport($request_data)
+    {
+        $url = $this->baseUrl . '/report/getReportContrast';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 激活设备
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-08
+     */
+    public function activateDevice($request_data){
+        $url = $this->baseUrl . '/report/activateCode';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+
+    /**
+     * 获取设备信息
+     * @author 唐远望
+     * @version 1.0
+     * @date 2026-01-08
+     */
+    public function getDeviceInfo($request_data){
+        $url = $this->baseUrl . '/report/getDeviceInfo';
+        $response = self::curl_post($url, $this->header, json_encode($request_data));
+        $response_data = json_decode($response, true);
+        return $response_data;
+    }
+}

+ 49 - 0
database/migrations/2026_04_03_000000_create_scenic_spot_table.php

@@ -0,0 +1,49 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateScenicSpotTable extends Migration
+{
+    /**
+     * 景区数据表
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('scenic_spot', function (Blueprint $table) {
+            $table->id();
+            $table->unsignedBigInteger('scenic_type_id')->default(0)->comment('景区类型ID');
+            $table->string('name', 200)->default('')->comment('景区名称');
+            $table->longText('intro')->nullable()->comment('景区介绍');
+            $table->decimal('longitude', 11, 8)->nullable()->comment('经度');
+            $table->decimal('latitude', 10, 8)->nullable()->comment('纬度');
+            $table->unsignedBigInteger('province_id')->default(0)->comment('省份ID');
+            $table->string('province_name', 64)->default('')->comment('省份名称');
+            $table->unsignedBigInteger('city_id')->default(0)->comment('城市ID');
+            $table->string('city_name', 64)->default('')->comment('城市名称');
+            $table->unsignedBigInteger('district_id')->default(0)->comment('区域ID');
+            $table->string('district_name', 64)->default('')->comment('区域名称');
+            $table->string('address', 500)->default('')->comment('详细地址');
+            $table->unsignedTinyInteger('status')->default(0)->comment('状态');
+            $table->unsignedInteger('insert_time')->default(0)->comment('写入时间');
+            $table->unsignedInteger('update_time')->default(0)->comment('更新时间');
+
+            $table->index('scenic_type_id');
+            $table->index('province_id');
+            $table->index('city_id');
+            $table->index('district_id');
+            $table->index('status');
+        });
+    }
+
+    /**
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('scenic_spot');
+    }
+}

+ 4 - 1
routes/api.php

@@ -33,4 +33,7 @@ Route::any('login/send_email_code', [App\Http\Controllers\Api\Login::class,'send
 //邮箱号码注册
 Route::any('login/email_register', [App\Http\Controllers\Api\Login::class, 'email_register']);
 // 个人信息详情
-Route::any('personnel/user_info', [App\Http\Controllers\Api\Personnel\User::class, 'user_info']);
+Route::any('personnel/user_info', [App\Http\Controllers\Api\Personnel\User::class, 'user_info']);
+
+//采集博物馆数据
+Route::any('museum/spot/collect_data', [App\Http\Controllers\Api\Museum\Spot::class, 'collect_data']);