A2C工单修复

This commit is contained in:
root
2026-07-03 20:12:20 +08:00
parent c3223f026e
commit 0f3eb53afe
21 changed files with 1561 additions and 172 deletions
@@ -47,16 +47,18 @@ class AntiBotConfigBuilder
'sessionTtlMinutes' => $ttlMinutes,
'businessHostHint' => $businessHostHint,
'landingUrlHint' => $landingUrlHint !== '' ? $landingUrlHint : '',
'cfCloudflareSolver' => self::defaultCfCloudflareSolver($ticketType),
'cfChallengeMode' => self::defaultCfChallengeMode($ticketType),
] + self::postCfReadyExtras($ticketType);
}
/**
* 会话 scopeA2C 短链固定业务域;火箭长链用动态 host、短链用 share.{token}
* 会话 scopeA2C 业务域+分享 id;火箭长链用动态 host、短链用 share.{token}
*/
public static function resolveSessionScope(string $ticketType, string $pageUrl, string $landingUrlHint = ''): string
{
if ($ticketType === 'a2c') {
return self::resolveA2cSessionHost($pageUrl, $landingUrlHint);
return self::resolveA2cSessionScope($pageUrl, $landingUrlHint);
}
if ($ticketType === 'huojian') {
@@ -135,10 +137,11 @@ class AntiBotConfigBuilder
if ($ticketType === 'a2c') {
return [
'postCfReadyUrlContains' => '/visitors/counter/share',
'postCfReadySelector' => '.btn-next',
'postCfReadyTimeoutMs' => 30000,
'postCfReadySelector' => '.el-table',
'postCfReadyApiUrl' => '/api/talk/counter/share/record/list',
'postCfReadyTimeoutMs' => 60000,
'postCfSettleMs' => 500,
'postCfSpaWaitMs' => 4000,
'postCfSpaWaitMs' => 8000,
];
}
@@ -162,10 +165,6 @@ class AntiBotConfigBuilder
private static function defaultSolverFallback(string $ticketType): bool
{
if ($ticketType === 'a2c') {
return false;
}
return true;
}
@@ -178,6 +177,26 @@ class AntiBotConfigBuilder
return true;
}
/**
* A2C 等为 CF Managed Challenge5s 盾),非独立 Turnstile 挂件
*/
private static function defaultCfChallengeMode(string $ticketType): string
{
if ($ticketType === 'a2c') {
return 'managed';
}
return '';
}
/**
* sitekey 缺失时是否允许 CapSolver AntiCloudflareTask(需 Node 侧 CAPTCHA_PROXY
*/
private static function defaultCfCloudflareSolver(string $ticketType): bool
{
return $ticketType === 'a2c';
}
/**
* 火箭/A2C 业务域 hint:优先长链动态 host,其次 landing 预解析
*/
@@ -223,6 +242,35 @@ class AntiBotConfigBuilder
return 'user.a2c.chat';
}
/**
* A2C 会话 scope:业务域 + 分享 id(避免多工单共用温池 Browser 互相干扰)
*/
private static function resolveA2cSessionScope(string $pageUrl, string $landingUrlHint = ''): string
{
$host = self::resolveA2cSessionHost($pageUrl, $landingUrlHint);
$shareId = self::extractA2cShareId($pageUrl);
if ($shareId === '' && $landingUrlHint !== '') {
$shareId = self::extractA2cShareId($landingUrlHint);
}
return $shareId !== '' ? $host . ':' . $shareId : $host;
}
/**
* 从 A2C 分享 URL 提取 id 查询参数
*/
private static function extractA2cShareId(string $url): string
{
$query = (string) parse_url($url, PHP_URL_QUERY);
if ($query === '') {
return '';
}
parse_str($query, $params);
$id = isset($params['id']) ? trim((string) $params['id']) : '';
return $id !== '' ? $id : '';
}
private static function resolveHuojianSessionScope(string $pageUrl, string $landingUrlHint = ''): string
{
$scope = HuojianUrlHelper::resolveSessionScope($pageUrl);
@@ -7,11 +7,12 @@ namespace app\common\library\scrm\spider;
use app\common\library\scrm\AbstractScrmSpider;
use app\common\library\scrm\AntiBotConfigBuilder;
use app\common\library\scrm\UnifiedScrmData;
use app\common\service\SplitPageUrlResolver;
/**
* A2C 云控蜘蛛(Real Browser 打开分享页 + 拦截加密 API + UI 翻页)
*
* 业务域 user.a2c.chat 无需 cf_clearance;短链 yyk.ink 仍由浏览器 follow 跳转
* 业务域 user.a2c.chat 在 CF 挑战页启用 CapSolver 兜底;短链 yyk.ink 预解析为长链后直达业务页
*/
class A2cSpider extends AbstractScrmSpider
{
@@ -27,6 +28,9 @@ class A2cSpider extends AbstractScrmSpider
private string $password;
/** @var string HTTP 预解析落地 URL(供 antiBot landingUrlHint */
private string $landingUrlHint = '';
private UnifiedScrmData $unifiedData;
public function __construct(
@@ -39,6 +43,7 @@ class A2cSpider extends AbstractScrmSpider
$this->pageUrl = $pageUrl;
$this->account = $account;
$this->password = $password;
$this->landingUrlHint = SplitPageUrlResolver::resolveFinalUrl($pageUrl);
$this->unifiedData = new UnifiedScrmData();
}
@@ -53,7 +58,7 @@ class A2cSpider extends AbstractScrmSpider
'authActions' => [
['type' => 'wait', 'ms' => 2000],
],
'antiBot' => AntiBotConfigBuilder::build('a2c', $this->pageUrl),
'antiBot' => AntiBotConfigBuilder::build('a2c', $this->pageUrl, $this->landingUrlHint),
];
}
@@ -80,7 +80,7 @@ class HuojianSpider extends AbstractScrmSpider
protected function parseToUnifiedData($detailData, array $allListPagesData): UnifiedScrmData
{
$unifiedData = $this->unifiedData;
$unifiedData->todayNewCount = (int) ($allListPagesData[0]['data']['counterWorker']['newTodayFriend'] ?? 0) + (int) ($allListPagesData[0]['data']['counterWorker']['newRemovedTodayFriend'] ?? 0);
$unifiedData->todayNewCount = (int) ($allListPagesData[0]['data']['counterWorker']['newTodayFriend'] ?? 0);
$count = 0;
foreach ($allListPagesData as $pageRaw) {
$records = $pageRaw['data']['counterCsAccountVo'] ?? [];