diff --git a/app/Console/Commands/Collector.php b/app/Console/Commands/Collector.php new file mode 100644 index 0000000..4dbbf14 --- /dev/null +++ b/app/Console/Commands/Collector.php @@ -0,0 +1,233 @@ +exists_update = false; + $this->scenic(); + $this->hotel(); + return Command::SUCCESS; + } + //php artisan collector + + //酒店采集 + private function hotel() + { + $http = Http::withOptions(['verify' => false]); + + $mddid = 10030; //10030==三亚 + for ($i=0; $i<10; $i++) { + $this->line('开始采集:第 ' . ($i + 1) . ' 页'); + $data = $http->get('https://m.mafengwo.cn/rest/hotel/hotels/', [ + 'filter' => [ + 'mddid' => $mddid + ], + 'page' => [ + 'mode' => 'sequential', + 'boundary' => $i * 20, //分页参数 + 'num' => 20 + ], + ]); + + if (empty($data['data']['list'])) { + continue; + } + + foreach ($data['data']['list'] as $v) { + if (empty($v['id'])) continue; + + if ($this->exists_update == false && CollectProduct::where(['unique_id' => $v['id'], 'site' => 1])->exists()) { + continue; + } + + $this->line('采集详情:' . $v['id']); + + //基本信息 + $params = [ + '_ts' => time() . '123', + 'hotel_id' => (string)$v['id'], + 'lat' => '', + 'lng' => '', + 'rmdd_id' => (string)$mddid, + ]; + $params['_sn'] = $this->_sn($params); + $data = $http->get('https://m.mafengwo.cn/hservice/detail/info/base_info', $params); + + if (empty($data['data']['info'])) { + continue; + } + $base_info = $data['data']['info']; + + //酒店详情 + $data = $http->get('https://m.mafengwo.cn/hservice/detail/info/guide_info', ['hotel_id' => $v['id']]); + $guide_info = $data['data']['info'] ?? []; + + //旅游须知 + $know = "

入住时间:" . (!empty($guide_info['check_in']['title']) ? $guide_info['check_in']['title'] : '') . "

"; + $know .= "

离店时间:" . (!empty($guide_info['check_out']['title']) ? $guide_info['check_out']['title'] : '') . "

"; + $know .= '

' . array_reduce($base_info['facility_sort'] ?? [], fn($v1, $v2) => $v1 . $v2['title'] ?? '') . '

'; + + //扩展字段 + $extends['field_1_tags'] = array_map(fn($v) => $v['title'] ?? '', $guide_info['facility'] ?? []); + $extends['field_1_name'] = $base_info['name']; + $extends['field_1_address'] = $base_info['address']; + $extends['field_1_latitude'] = $base_info['lat']; + $extends['field_1_longitude'] = $base_info['lng']; + + CollectProduct::updateOrCreate(['unique_id' => $v['id'], 'site' => 1], [ + 'unique_id' => $v['id'], + 'site' => 1, + 'type' => 1, //0:旅游线路、1:酒店、2:景区、3:餐厅、4:车队、5:单项 + 'title' => mb_substr($base_info['name'] ?? '' . $base_info['level'] ?? '', 0, 255), + 'price' => mt_rand(150, 350), + 'original_price' => mt_rand(350, 550), + 'pictures' => array_map(fn($v) => $v['url'] ?? '', $base_info['album'] ?? []) ?? [], + 'stock' => mt_rand(1000, 9999), + 'sale' => $base_info['num_collect'] ?? 0, + 'status' => -2, //-2下架 + 'know' => $know, + 'content' => $guide_info['intro'] ?? '', + 'extends' => $extends, + 'logitude' => $base_info['lng'] ?? 0, + 'latitude' => $base_info['lat'] ?? 0, + 'address' => $base_info['address'] ?? '', + ]); + $this->line("{$v['id']} 采集结束" . PHP_EOL); + } + $this->line('第 ' . ($i + 1) . ' 页采集结束' . PHP_EOL); + } + } + + //酒店详情计算_sn + private function _sn($params): string + { + ksort($params); + return substr(md5(json_encode($params) . 'c9d6618dbc657b41a66eb0af952906f1'), 2, 10); + } + + //景区采集 + private function scenic() + { + $http = Http::withOptions(['verify' => false]); + + for($i=0; $i<10; $i++) { + $data = $http->get('https://m.mafengwo.cn/sales/ajax.php', [ + 'sF' => 'search_new_list', + 'offset' => $i * 10, //分页参数 + ]); + + if (empty($data['data'])) { + continue; + } + $data = $data['data']; + + preg_match_all('/exists_update == false && CollectProduct::where(['unique_id' => $id, 'site' => 1])->exists()) { + continue; + } + + $this->line('开始采集:' . $id); + $info = $http->get('https://m.mafengwo.cn/sales/detail/index/info?id=' . $id); + + //旅游须知 + $know = $info['data']['list']['content'][0]['content'] ?? []; + if (isset($info['data']['list']['content'][0]['content']) && is_array($info['data']['list']['content'][0]['content'])) { + $know = current(array_filter($info['data']['list']['content'][0]['content'], fn($v) => isset($v['name']) && $v['name'] == '购买须知')); + if (isset($know['content']) && is_array($know['content'])) { + $know = array_reduce( + $know['content'], fn($v1, $v2) => $v1 . + (isset($v2['name']) && is_string($v2['name']) ? "

{$v2['name']}

" : '') . + (isset($v2['content']) && is_string($v2['content']) ? $v2['content'] : '') + ); + } + } + + //产品详情 + $content = ''; + if (isset($info['data']['list']['content'][0]['content']) && is_array($info['data']['list']['content'][0]['content'])) { + $content = current(array_filter($info['data']['list']['content'][0]['content'], fn($v) => isset($v['key']) && $v['key'] == 'introduce')); + if (isset($content['content']) && is_array($content['content'])) { + $content = current(array_filter($content['content'], fn($v) => isset($v['key']) && $v['key'] == 'introduction')); + $content = is_string($content['content']) ? $content['content'] : ''; + } else { + $content = ''; + } + } + + //扩展字段 + $extends = []; + if (isset($info['data']['list']['base']['tags']) && is_array($info['data']['list']['base']['tags'])) { + foreach ($info['data']['list']['base']['tags'] as $tag) { + $extends['field_2_project'][] = ['name' => $tag, 'num' => '', 'price' => '']; + } + } + + CollectProduct::updateOrCreate(['unique_id' => $id, 'site' => 1], [ + 'unique_id' => $id, + 'site' => 1, + 'type' => 2, //0:旅游线路、1:酒店、2:景区、3:餐厅、4:车队、5:单项 + 'title' => mb_substr($info['data']['list']['base']['title'] ?? '', 0, 255), + 'price' => $info['data']['list']['base']['price_zhanshi'] ?? 0, + 'original_price' => ($info['data']['list']['base']['price_zhanshi'] ?? 0) * 1.58, + 'pictures' => $info['data']['list']['base']['imgList'] ?? [], + 'stock' => mt_rand(1000, 9999), + 'sale' => $info['data']['list']['base']['sold']['num'] ?? 0, + 'status' => -2, //-2下架 + 'know' => $know, + 'content' => $content, + 'extends' => $extends, + 'logitude' => 0, + 'latitude' => 0, + 'address' => '', + ]); + + $this->line($id . ' 采集完毕!' . PHP_EOL); + } + } + } +} diff --git a/app/Models/CollectProduct.php b/app/Models/CollectProduct.php new file mode 100644 index 0000000..2305f5f --- /dev/null +++ b/app/Models/CollectProduct.php @@ -0,0 +1,18 @@ + 'json', + 'extends' => 'json', + ]; +}