diff --git a/app/common/controller/UsedCarController.php b/app/common/controller/UsedCarController.php index d5c4ee6..5eba0d4 100644 --- a/app/common/controller/UsedCarController.php +++ b/app/common/controller/UsedCarController.php @@ -161,9 +161,9 @@ class UsedCarController extends BaseController 'product_name' => $info['title'], 'price' => $info['price']<200 ? $info['price']*10000 : $info['price'], 'source_place' => $info['source_place'], - 'displacement' => $info['capacity'], //排量 + 'displacement' => $info['capacity']??'', //排量 'mileage' => $info['usage_mileage']*10000, //里程 - 'power' => $info['horsepower'], //马力 + 'power' => $info['horsepower']??'', //马力 'body_color' => $info['body_color'], 'images' => $info['image'], 'image_pull' => $info['image_pull'], diff --git a/app/common/service/UsedCarService.php b/app/common/service/UsedCarService.php index 7e29b9b..fc6fcc1 100644 --- a/app/common/service/UsedCarService.php +++ b/app/common/service/UsedCarService.php @@ -447,8 +447,8 @@ class UsedCarService } $info = $usedCarCrawl->crawlCar($finalUrl); break; - case str_contains($url,'che168.com'): //汽车之家 - throw new \Exception('加紧开发中'); + case str_contains($url,'che168.com/dealer'): //汽车之家 + $info = $usedCarCrawl->crawlChe168Car($url); break; default: Log::info('未知链接:'.$url); diff --git a/app/common/utils/crawl/service/UsedCarCrawlSingle.php b/app/common/utils/crawl/service/UsedCarCrawlSingle.php index 1f45f1b..c793e60 100644 --- a/app/common/utils/crawl/service/UsedCarCrawlSingle.php +++ b/app/common/utils/crawl/service/UsedCarCrawlSingle.php @@ -114,6 +114,114 @@ class UsedCarCrawlSingle return $info; } + /** + * 抓取汽车之家数据 + * @param Request $request + */ + public function crawlChe168Car(string $url) + { + // 解析 URL获取车辆id + $parsedUrl = parse_url($url); + $path = $parsedUrl['path']; // "/dealer/162138/56723550.html" + // 使用 pathinfo 获取文件名 + $pathParts = explode('/', $path); + $filename = end($pathParts); // "56723550.html" + $carId = pathinfo($filename, PATHINFO_FILENAME); // "56723550" + + // 初始化 Guzzle 客户端 + $client = new Client([ + 'headers' => [ + 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', + 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Referer' => 'https://www.che168.com/', + ], + 'verify' => false, + 'timeout' => 10, + ]); + + + // 请求 HTML + $response = $client->get($url); + $html = (string)$response->getBody(); + + // 检查是否获取到 HTML + if (empty($html)) { + throw new \Exception('无法获取页面 HTML'); + } + + // 使用 QueryList 解析 HTML + $ql = QueryList::html($html); + file_put_contents(runtime_path('168.html'),$html); + + // 解析车辆列表,每辆车可能在 li.cards-li 或类似类名里 + $cars = $ql->find('div#nav1 ul.basic-item-ul li')->map(function($item) { + $attribute = []; + $field = $item->find('.item-name')->text(); + $value = $item->text(); + $title = ['product_name' => '产品名称','plate_time' => '上牌时间', 'mileage' => '表显里程', 'capacity' => '排       量', 'source_place'=> '所  在  地', 'body_color'=>'车身颜色','condition_desc'=>'车况介绍',]; + $title_key = array_flip($title); + if(in_array($field,$title)){ + $attribute[$title_key[$field]] = str_replace($field, '', $value); + } + + // 车辆图片 +// $img = $item->find('.list-photo img')->attr('src'); + + return $attribute; + })->all(); + + $cars = array_filter($cars); + $cars = array_merge(...$cars); + $cars['product_name'] = $cars['car_name'] = $ql->find('div.car-box .car-brand-name')->text(); + $cars['price'] = $ql->find('span.price')->text(); + $cars['price'] = !empty($cars['price'])?str_replace('万', '', $cars['price'])*10000:0; + //$cars['price'] = $ql->find('#overlayPrice')->text(); + $cars['title'] = $cars['product_name']; + $cars['condition_desc'] = $ql->find('div.leave-message-box #messageBox')->text(); + $cars['usage_mileage'] = str_replace('万公里', '', $cars['mileage']); + + //品牌与车系 + $links = $ql->find('.bread-crumbs a')->map(function ($a) { + return trim($a->text()); + })->all(); + $cars['brand_name'] = $links[3] ?str_replace('二手','',$links[3]): null; + $cars['brand_id'] = 0; + $cars['series_name'] = $links[4] ?str_replace('二手','',$links[4]): null; + $cars['series_id'] = 0; + $cars['car_id'] = 0; + $info = explode(' ',$cars['product_name']); + $info = array_filter($info, function($item) { + return str_contains($item, '款'); + }); + $year = end($info); + $cars['year'] = !empty($year) ? str_replace('款', '', $year):''; + + //图片 + $images = $ql->find('#pic_li img')->map(function ($img) { + // 只取 data-original + $src = $img->attr('data-original'); + + if (!$src) { + return null; + } + + // 补全 https + if (str_starts_with($src, '//')) { + $src = 'https:' . $src; + } + + return $src; + })->filter()->values()->all(); + + $saveDir = public_path('uploads/usedcar/' . $carId); + $cars['used_car_id'] = $carId; + $image = $this->uploadAndRemove($images, $saveDir); + $cars['image'] = $image['image']; + $cars['image_pull'] = $image['image_pull']; + + return $cars; + } + /** * 下载 -> 上传 -> 删除本地 *