关键词抓取

This commit is contained in:
2026-03-05 15:47:30 +08:00
parent 9c7efff01f
commit 0d895688c3
3 changed files with 158 additions and 0 deletions
@@ -187,6 +187,27 @@ class UsedCarController extends BaseController
}
}
/**
* 关键词搜索懂车帝车型数据
*/
public function crawlKeyword(Request $request): Response
{
$this->requireAuth($request);
$keyword = $request->post('keyword') ?: $request->get('keyword');
if (empty($keyword)) {
return $this->error('关键词不能为空');
}
try {
$crawlService = new \app\Service\UsedCarCrawlService();
$data = $crawlService->searchByKeyword($keyword);
return $this->success($data);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
/**
* 生成PDF
*/
+136
View File
@@ -521,4 +521,140 @@ class UsedCarCrawlService
return $result;
}
/**
* 通过关键词搜索懂车帝车系信息
*
* @param string $keyword 搜索关键词(如 "奥迪A4")
* @return array 品牌和车系信息
* @throws \Exception
*/
public function searchByKeyword(string $keyword): array
{
// 访问懂车帝搜索页面获取第一个结果的链接
$searchUrl = "https://www.dongchedi.com/search?keyword=" . urlencode($keyword);
try {
$html = $this->fetchHtml($searchUrl);
$ql = QueryList::html($html);
// 查找"查看全部"按钮的链接
$href = '';
$ql->find('a.fold-btn')->each(function ($item) use (&$href) {
$itemHref = $item->attr('href');
if ($itemHref) {
$href = $itemHref;
}
});
if (empty($href)) {
throw new \Exception('未找到相关车系,请使用更精确的关键词');
}
// 提取车系ID
$seriesId = $this->extractSeriesId($href);
if (!$seriesId) {
throw new \Exception('无法解析车系ID');
}
// 获取品牌和车系信息
return $this->getBrandSeries($seriesId);
} catch (\Exception $e) {
throw new \Exception('搜索失败: ' . $e->getMessage());
}
}
/**
* 获取品牌和车系名称
*
* @param string $seriesId 车系ID
* @return array 包含品牌和车系信息的数组
* @throws \Exception
*/
public function getBrandSeries(string $seriesId): array
{
$url = "https://www.dongchedi.com/auto/series/" . $seriesId . "?anchorId=carModels";
try {
$html = $this->fetchHtml($url);
$ql = QueryList::html($html);
// 从面包屑导航中提取品牌和车系
$breadcrumbs = [];
$ql->find('div.breadcrumb_wrap__2GLeU span')->each(function ($item) use (&$breadcrumbs) {
$breadcrumbs[] = trim($item->text());
});
$brand = $breadcrumbs[2] ?? '';
$series = $breadcrumbs[3] ?? '';
// 获取车型列表
$models = $this->getSeriesModels($seriesId);
return [
'brand' => $brand,
'series' => $series,
'series_id' => $seriesId,
'models' => $models,
];
} catch (\Exception $e) {
throw new \Exception('获取车系信息失败: ' . $e->getMessage());
}
}
/**
* 获取车系下的车型列表
*
* @param string $seriesId 车系ID
* @return array 车型列表
*/
public function getSeriesModels(string $seriesId): array
{
$url = "https://www.dongchedi.com/auto/series/" . $seriesId . "?anchorId=carModels";
$models = [];
try {
$html = $this->fetchHtml($url);
$ql = QueryList::html($html);
// 解析车型列表
$ql->find('div.carModelsPager__EiwGC a.model-item__1r8j')->each(function ($item) use (&$models) {
$modelName = trim($item->text());
$modelUrl = $item->attr('href');
if ($modelName) {
$models[] = [
'name' => $modelName,
'url' => $modelUrl ? 'https://www.dongchedi.com' . $modelUrl : '',
];
}
});
return $models;
} catch (\Exception) {
// 车型解析失败,返回空数组
return [];
}
}
/**
* 从懂车帝URL中提取车系ID
*
* @param string $url 懂车帝URL
* @return string|null 车系ID
*/
private function extractSeriesId(string $url): ?string
{
// 匹配 /auto/series/x123/ 格式
if (preg_match('/\/auto\/series\/(\d+)/', $url, $matches)) {
return $matches[1];
}
// 匹配 /auto/series/x123/params/ 格式
if (preg_match('/\/auto\/series\/(\d+)/', $url, $matches)) {
return $matches[1];
}
return null;
}
}
+1
View File
@@ -72,6 +72,7 @@ Route::group('/api/v1/usedcar', function () {
Route::post('/status', [app\controller\UsedCarController::class, 'updateStatus']);
Route::post('/crawl/url', [app\controller\UsedCarController::class, 'crawlByUrl']);
Route::post('/crawl/mobile', [app\controller\UsedCarController::class, 'crawlMobileUrl']);
Route::post('/crawl/keyword', [app\controller\UsedCarController::class, 'crawlKeyword']);
Route::post('/pdf/generate', [app\controller\UsedCarController::class, 'generatePdf']);
Route::get('/pdf/download', [app\controller\UsedCarController::class, 'downloadPdf']);
Route::get('/pdf/url', [app\controller\UsedCarController::class, 'getPdfUrl']);