account = $account; $this->password = $password; $this->pageUrl = $pageUrl; $this->landingUrlHint = SplitPageUrlResolver::resolveFinalUrl($pageUrl); $this->unifiedData = new UnifiedScrmData(); } protected function getSpiderConfig() { $antiBot = $this->buildAntiBotConfig(); $this->logDebug('huojian spider config', [ 'pageUrl' => $this->pageUrl, 'landingUrlHint' => $this->landingUrlHint, 'sessionKey' => $antiBot['sessionKey'] ?? '', 'businessHostHint' => $antiBot['businessHostHint'] ?? '', 'cfClearanceRequired' => $antiBot['cfClearanceRequired'] ?? null, ]); return [ 'pageUrl' => $this->pageUrl, 'listApi' => self::API_LIST, 'listMethod' => 'POST', 'paginationMode' => self::MODE_UI, 'authActions' => [ ['type' => 'vue_fill', 'selector' => '.el-message-box__input input', 'value' => $this->password], ['type' => 'wait', 'ms' => 500], ['type' => 'vue_click', 'selector' => '.el-message-box__btns .el-button--primary'], ['type' => 'wait', 'ms' => 2000], ], 'antiBot' => $antiBot, ]; } /** * 对齐生产 AntiBotConfigBuilder 火箭策略(长链 host 动态解析) * * @return array */ private function buildAntiBotConfig() { $sessionScope = $this->resolveHuojianSessionScope(); $businessHostHint = $this->resolveHuojianBusinessHostHint(); return [ 'enabled' => true, 'profile' => 'real', 'turnstile' => true, 'solverFallback' => true, 'cfClearanceRequired' => true, 'sessionKey' => 'huojian:' . $sessionScope, 'challengeTimeoutMs' => 60000, 'landingUrlHint' => $this->landingUrlHint, 'businessHostHint' => $businessHostHint, 'postCfReadyUrlContains' => '/gds', 'postCfReadySelector' => '.el-message-box__input', 'postCfReadyTimeoutMs' => 45000, 'postCfSettleMs' => 500, 'postCfSpaWaitMs' => 8000, ]; } private function isHuojianLongLinkUrl($pageUrl) { $path = (string) parse_url($pageUrl, PHP_URL_PATH); if ($path === '' || strpos($path, '/gds') === false) { return false; } $query = []; parse_str((string) parse_url($pageUrl, PHP_URL_QUERY), $query); return trim((string) ($query['link'] ?? '')) !== ''; } private function extractHuojianShareToken($pageUrl) { if ($this->isHuojianLongLinkUrl($pageUrl)) { $query = []; parse_str((string) parse_url($pageUrl, PHP_URL_QUERY), $query); return trim((string) ($query['link'] ?? '')); } $path = trim((string) parse_url($pageUrl, PHP_URL_PATH), '/'); if ($path === '' || strpos($path, '/') !== false) { return ''; } if (preg_match('/^[a-zA-Z0-9]+$/', $path) !== 1) { return ''; } return $path; } private function resolveHuojianSessionScope() { if ($this->isHuojianLongLinkUrl($this->pageUrl)) { return strtolower((string) parse_url($this->pageUrl, PHP_URL_HOST)); } $token = $this->extractHuojianShareToken($this->pageUrl); if ($token !== '') { return 'share.' . $token; } if ($this->landingUrlHint !== '' && $this->isHuojianLongLinkUrl($this->landingUrlHint)) { return strtolower((string) parse_url($this->landingUrlHint, PHP_URL_HOST)); } return 'unknown'; } private function resolveHuojianBusinessHostHint() { if ($this->isHuojianLongLinkUrl($this->pageUrl)) { return strtolower((string) parse_url($this->pageUrl, PHP_URL_HOST)); } if ($this->landingUrlHint !== '' && $this->isHuojianLongLinkUrl($this->landingUrlHint)) { return strtolower((string) parse_url($this->landingUrlHint, PHP_URL_HOST)); } return ''; } protected function extractListTotalPages($listFirstPageData, $countData = null) { return 1; } protected function buildListPageParams($page) { return []; } protected function getUiPaginationConfig() { return []; } protected function parseToUnifiedData($detailData, $allListPagesData) { $unifiedData = $this->unifiedData; $unifiedData->todayNewCount = (int) ($allListPagesData[0]['data']['counterWorker']['newTodayFriend'] ?? 0) + (int) ($allListPagesData[0]['data']['counterWorker']['newRemovedTodayFriend'] ?? 0); $count = 0; foreach ($allListPagesData as $pageRaw) { $records = $pageRaw['data']['counterCsAccountVo'] ?? []; foreach ($records as $item) { if (!empty($item['accountLogin'])) { $number = $item['accountLogin']; $isOnline = (isset($item['accountStatus']) && (int) $item['accountStatus'] === 1); $count++; $unifiedData->addNumber($number, $isOnline, (int) ($item['newTodayFriend'] ?? 0)); } } } $unifiedData->total = $count; return $unifiedData; } }