添加whatshub工单
This commit is contained in:
Regular → Executable
Regular → Executable
+10
-3
@@ -107,6 +107,11 @@ abstract class AbstractScrmSpider
|
||||
if ($detailApi) { $apiUrlsToIntercept[] = $detailApi; }
|
||||
if ($countApi) { $apiUrlsToIntercept[] = $countApi; }
|
||||
// var_dump($apiUrlsToIntercept);
|
||||
// dump([
|
||||
// 'pageUrl' => $config['pageUrl'],
|
||||
// 'apiUrls' => $apiUrlsToIntercept,
|
||||
// 'authActions' => $config['authActions']
|
||||
// ]);
|
||||
// 【阶段一】:初始化并首屏拦截
|
||||
$initResult = $this->requestNode('/api/auth-and-intercept', [
|
||||
'pageUrl' => $config['pageUrl'],
|
||||
@@ -120,7 +125,8 @@ abstract class AbstractScrmSpider
|
||||
|
||||
$interceptedApis = $initResult['interceptedApis'];
|
||||
$cookies = $initResult['cookies'];
|
||||
// dd($interceptedApis);
|
||||
$finalPageUrl = $initResult['finalPageUrl'] ?? $config['pageUrl'];
|
||||
|
||||
// 必须拦截到 List 接口,否则无法继续
|
||||
if (!isset($interceptedApis[$listApi])) {
|
||||
throw new Exception("致命错误:未能拦截到必须的列表接口 [{$listApi}]");
|
||||
@@ -133,7 +139,7 @@ abstract class AbstractScrmSpider
|
||||
// dd($countData);
|
||||
$listApiNode = $interceptedApis[$listApi];
|
||||
$allListPagesData = [$listApiNode['data']]; // 初始化列表容器,装入第一页数据
|
||||
|
||||
// dd($allListPagesData);exit;
|
||||
$totalPages = $this->extractListTotalPages($listApiNode['data'], $countData);
|
||||
|
||||
$mode = $config['paginationMode'] ?? self::MODE_FETCH;
|
||||
@@ -163,7 +169,7 @@ abstract class AbstractScrmSpider
|
||||
if ($pResult['success']) $allListPagesData[] = $pResult['data'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 策略 2:强制 UI 点击
|
||||
elseif ($mode === self::MODE_UI) {
|
||||
$uiConfig = $this->getUiPaginationConfig();
|
||||
@@ -176,6 +182,7 @@ abstract class AbstractScrmSpider
|
||||
$uiResult = $this->requestNode('/api/ui-pagination', [
|
||||
'apiUrl' => $listApi,
|
||||
'pageUrl' => $config['pageUrl'],
|
||||
'finalPageUrl' => $finalPageUrl,
|
||||
'nextBtnSelector' => $uiConfig['nextBtnSelector'],
|
||||
'waitMs' => $uiConfig['waitMs'] ?? 2000,
|
||||
'clicksToPerform' => $clicksToPerform,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
// Chatknow SCRM工单
|
||||
require_once __DIR__ . '/AbstractScrmSpider.class.php';
|
||||
|
||||
class Chatknow extends AbstractScrmSpider
|
||||
{
|
||||
const API_LIST = '/user/user/UserInfoChildChannel/list'; // 列表API地址
|
||||
const API_DETAILS = ''; // 详情API地址
|
||||
const API_COUNT = ''; // 总数API地址
|
||||
const DEFAULT_PER_PAGE_COUNT = 10; // List默认每页显示的数量
|
||||
private $pageUrl;
|
||||
private $account;
|
||||
private $password;
|
||||
private $unifiedData;
|
||||
|
||||
// 实例化时动态传入账号和密码
|
||||
public function __construct($pageUrl, $account, $password, $nodeHost = 'http://127.0.0.1:3001')
|
||||
{
|
||||
parent::__construct($nodeHost);
|
||||
$this->account = $account;
|
||||
$this->password = $password;
|
||||
$this->pageUrl = $pageUrl;
|
||||
|
||||
$this->unifiedData = new UnifiedScrmData();
|
||||
}
|
||||
|
||||
protected function getSpiderConfig()
|
||||
{
|
||||
return [
|
||||
'pageUrl' => $this->pageUrl,
|
||||
'apiUrls' => [self::API_LIST],
|
||||
'listApi' => self::API_LIST, // 必须,第一页的列表数据
|
||||
// 'detailApi' => self::API_DETAILS, // 选填
|
||||
// 'countApi' => self::API_COUNT,
|
||||
|
||||
'listMethod' => 'GET',
|
||||
|
||||
'paginationMode' => self::MODE_UI,
|
||||
|
||||
'authActions' => [
|
||||
// ['type' => 'vue_select', 'selector' => 'input[type="password"]', 'value' => $this->password],
|
||||
// ['type' => 'type', 'selector' => '#username_input', 'value' => $this->account],
|
||||
// ['type' => 'vue_click', 'selector' => '.layui-btn', 'text' => '搜索'],
|
||||
|
||||
['type' => 'wait', 'ms' => 4000]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// 只负责解析 List 的总页数
|
||||
protected function extractListTotalPages($listFirstPageData, $countData = null)
|
||||
{
|
||||
$default_per_page_count = self::DEFAULT_PER_PAGE_COUNT;
|
||||
$this->unifiedData->total = $listFirstPageData['total'];
|
||||
$this->unifiedData->todayNewCount = $listFirstPageData['data']['today_num'];
|
||||
|
||||
if($listFirstPageData['total'] <= $default_per_page_count) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ceil($listFirstPageData['total']/$default_per_page_count);
|
||||
}
|
||||
|
||||
// 只负责组装 List 的翻页参数
|
||||
protected function buildListPageParams($page)
|
||||
{
|
||||
return ['page' => $page, 'limit' => self::DEFAULT_PER_PAGE_COUNT];
|
||||
}
|
||||
|
||||
// 提供 List 的下一页按钮信息
|
||||
protected function getUiPaginationConfig()
|
||||
{
|
||||
return [
|
||||
'nextBtnSelector' => '.tabs-content .arco-pagination-item-next',
|
||||
'waitMs' => 2000
|
||||
];
|
||||
}
|
||||
|
||||
// 清爽至极的数据清洗:详情是详情,列表是列表
|
||||
protected function parseToUnifiedData($detailData, $allListPagesData)
|
||||
{
|
||||
$unifiedData = $this->unifiedData;
|
||||
|
||||
// 循环合并了所有页数的 List 数组
|
||||
foreach ($allListPagesData as $pageRaw) {
|
||||
$records = $pageRaw['rows'] ?? [];
|
||||
foreach ($records as $item) {
|
||||
if(!empty($item['username'])) {
|
||||
$number = $item['username'] ?? null;
|
||||
$isOnline = (isset($item['state']) && $item['state'] == 1);
|
||||
|
||||
$unifiedData->addNumber($number, $isOnline, $item['today_num']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $unifiedData;
|
||||
}
|
||||
}
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
// Whatshub 工单平台
|
||||
|
||||
require_once __DIR__ . '/AbstractScrmSpider.class.php';
|
||||
|
||||
class Whatshub extends AbstractScrmSpider
|
||||
{
|
||||
const API_LIST = '/api/whatshub-counter/workShare/open/detail'; // 列表API地址
|
||||
const API_DETAILS = '/api/whatshub-counter/workShare/open/statistics'; // 详情API地址
|
||||
const API_COUNT = ''; // 总数API地址
|
||||
const DEFAULT_PER_PAGE_COUNT = 20; // List默认每页显示的数量
|
||||
private $pageUrl;
|
||||
private $account;
|
||||
private $password;
|
||||
private $unifiedData;
|
||||
|
||||
// 实例化时动态传入账号和密码
|
||||
public function __construct($pageUrl, $account, $password, $nodeHost = 'http://127.0.0.1:3001')
|
||||
{
|
||||
parent::__construct($nodeHost);
|
||||
$this->account = $account;
|
||||
$this->password = $password;
|
||||
$this->pageUrl = $pageUrl;
|
||||
|
||||
$this->unifiedData = new UnifiedScrmData();
|
||||
}
|
||||
|
||||
protected function getSpiderConfig()
|
||||
{
|
||||
$host = (string) parse_url($this->pageUrl, PHP_URL_HOST);
|
||||
return [
|
||||
'pageUrl' => $this->pageUrl,
|
||||
'apiUrls' => [self::API_LIST, self::API_DETAILS],
|
||||
|
||||
// 明确指派角色
|
||||
'listApi' => self::API_LIST, // 必须
|
||||
|
||||
'listMethod' => 'POST',
|
||||
'paginationMode' => self::MODE_UI,
|
||||
|
||||
'authActions' => [
|
||||
// 1. 填入密码:寻找 class 包含 el-message-box__input 下面的任意 input
|
||||
// Node.js 会自动扫描所有匹配项,并只把密码强行注入到那个“肉眼可见”的框里
|
||||
['type' => 'vue_fill', 'selector' => '.el-input__inner', 'value' => $this->password],
|
||||
|
||||
// 2. 停顿 500ms,让 Vue 绑定的 v-model 彻底反应过来
|
||||
['type' => 'wait', 'ms' => 500],
|
||||
|
||||
// 3. 点击确认:寻找 MessageBox 底部的蓝色 primary 确认按钮
|
||||
// 同样利用 vue_click 的可见性过滤,无视隐藏的旧弹窗按钮
|
||||
['type' => 'vue_click', 'selector' => '.vxe-button-group .theme--primary'],
|
||||
|
||||
// 4. 等待弹窗淡出,接口开始请求
|
||||
['type' => 'wait', 'ms' => 2200]
|
||||
],
|
||||
// Whatshub 专用:Real Browser + Turnstile + Captcha API 兜底 + 会话复用
|
||||
'antiBot' => [
|
||||
'enabled' => true,
|
||||
'profile' => 'real',
|
||||
'turnstile' => true,
|
||||
'solverFallback' => true,
|
||||
'sessionKey' => 'whatshub:' . $host,
|
||||
'challengeTimeoutMs' => 60000,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// 只负责解析 List 的总页数
|
||||
protected function extractListTotalPages($listFirstPageData, $countData = null)
|
||||
{
|
||||
$default_per_page_count = self::DEFAULT_PER_PAGE_COUNT;
|
||||
$this->unifiedData->total = $listFirstPageData['data']['total'];
|
||||
|
||||
if($this->unifiedData->total <= $default_per_page_count) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ceil($this->unifiedData->total/$default_per_page_count);
|
||||
}
|
||||
|
||||
// 没有分页返回空数组
|
||||
protected function buildListPageParams($page)
|
||||
{
|
||||
return ['pageNum' => $page, 'pageSize' => self::DEFAULT_PER_PAGE_COUNT];
|
||||
}
|
||||
|
||||
// 提供 List 的下一页按钮信息
|
||||
protected function getUiPaginationConfig()
|
||||
{
|
||||
return [
|
||||
'nextBtnSelector' => '.vxe-pager--next-btn',
|
||||
'waitMs' => 1500
|
||||
];
|
||||
}
|
||||
|
||||
// 清爽至极的数据清洗:详情是详情,列表是列表
|
||||
protected function parseToUnifiedData($detailData, $allListPagesData)
|
||||
{
|
||||
$unifiedData = $this->unifiedData;
|
||||
|
||||
// 1. 如果捕获到了详情数据,提取今日新增
|
||||
if ($detailData) {
|
||||
$unifiedData->todayNewCount = (int)($detailData['data']['dayNewFans'] ?? 0);
|
||||
}
|
||||
|
||||
// 2. 循环合并了所有页数的 List 数组
|
||||
foreach ($allListPagesData as $pageRaw) {
|
||||
$records = $pageRaw['data']['rows'] ?? [];
|
||||
foreach ($records as $item) {
|
||||
if(!empty($item['account'])) {
|
||||
$number = $item['account'] ?? null;
|
||||
$isOnline = (isset($item['isOnline']) && $item['isOnline'] == 1);
|
||||
|
||||
$unifiedData->addNumber($number, $isOnline, $item['dayNewFans']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 🚀 3. 终极统计:所有翻页数据均已入库,此时再统计真实的 Total 总数
|
||||
$unifiedData->total = count($unifiedData->numbers);
|
||||
|
||||
return $unifiedData;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+9
-9
@@ -5,10 +5,10 @@ require_once __DIR__ . '/AbstractScrmSpider.class.php';
|
||||
|
||||
class Xinghe extends AbstractScrmSpider
|
||||
{
|
||||
const API_LIST = '/share/share/api_yinliu_count.html'; // 列表API地址
|
||||
const API_DETAILS = ''; // 详情API地址
|
||||
const API_COUNT = ''; // 总数API地址
|
||||
const DEFAULT_PER_PAGE_COUNT = 10; // List默认每页显示的数量
|
||||
const API_LIST = '/share/share/api_yinliu_count.html'; // 列表API地址
|
||||
const API_DETAILS = ''; // 详情API地址
|
||||
const API_COUNT = ''; // 总数API地址
|
||||
const DEFAULT_PER_PAGE_COUNT = 10; // List默认每页显示的数量
|
||||
private $pageUrl;
|
||||
private $account;
|
||||
private $password;
|
||||
@@ -29,7 +29,7 @@ class Xinghe extends AbstractScrmSpider
|
||||
{
|
||||
return [
|
||||
'pageUrl' => $this->pageUrl,
|
||||
'apiUrls' => [self::API_LIST . "?page=1&limit=10"],
|
||||
'apiUrls' => [self::API_LIST . "?page=1&limit=10&is_repet=1"],
|
||||
'listApi' => self::API_LIST, // 必须,第一页的列表数据
|
||||
// 'detailApi' => self::API_DETAILS, // 选填
|
||||
// 'countApi' => self::API_COUNT,
|
||||
@@ -39,9 +39,9 @@ class Xinghe extends AbstractScrmSpider
|
||||
'paginationMode' => self::MODE_FETCH,
|
||||
|
||||
'authActions' => [
|
||||
// ['type' => 'type', 'selector' => 'input[type="password"]', 'value' => $this->password],
|
||||
// ['type' => 'vue_select', 'selector' => 'input[type="password"]', 'value' => $this->password],
|
||||
// ['type' => 'type', 'selector' => '#username_input', 'value' => $this->account],
|
||||
// ['type' => 'press', 'key' => 'Enter'],
|
||||
// ['type' => 'vue_click', 'selector' => '.layui-btn', 'text' => '搜索'],
|
||||
|
||||
['type' => 'wait', 'ms' => 2000]
|
||||
]
|
||||
@@ -53,7 +53,7 @@ class Xinghe extends AbstractScrmSpider
|
||||
{
|
||||
$default_per_page_count = self::DEFAULT_PER_PAGE_COUNT;
|
||||
$this->unifiedData->total = $listFirstPageData['count'];
|
||||
$this->unifiedData->todayNewCount = $listFirstPageData['totalRow']['day_sum'];
|
||||
// $this->unifiedData->todayNewCount = $listFirstPageData['totalRow']['day_sum'];
|
||||
|
||||
if($listFirstPageData['count'] <= $default_per_page_count) {
|
||||
return 1;
|
||||
@@ -84,7 +84,7 @@ class Xinghe extends AbstractScrmSpider
|
||||
|
||||
// 循环合并了所有页数的 List 数组
|
||||
foreach ($allListPagesData as $pageRaw) {
|
||||
$records = $pageRaw['data'] ?? [];
|
||||
$records = $pageRaw['data'] ?? [];
|
||||
foreach ($records as $item) {
|
||||
if(!empty($item['user'])) {
|
||||
$number = $item['user'] ?? null;
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/UnifiedScrmData.class.php';
|
||||
|
||||
/**
|
||||
* 数据爬虫类
|
||||
* 用于处理需要先获取 Token 授权,再读取接口数据的场景
|
||||
*/
|
||||
class Xinghe
|
||||
{
|
||||
private $cookieFile;
|
||||
private $ch; // cURL 句柄
|
||||
private $pageUrl;
|
||||
private $account;
|
||||
private $password;
|
||||
private $unifiedData;
|
||||
private $baseUrl;
|
||||
|
||||
/**
|
||||
* 构造函数:初始化 cURL 和 Cookie 文件
|
||||
*/
|
||||
public function __construct($pageUrl, $username, $password)
|
||||
{
|
||||
$this->pageUrl = $pageUrl;
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
|
||||
$parsedUrl = parse_url($pageUrl);
|
||||
$scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] . '://' : '';
|
||||
$host = isset($parsedUrl['host']) ? $parsedUrl['host'] : '';
|
||||
$baseUrl = $scheme . $host;
|
||||
$this->baseUrl = $baseUrl;
|
||||
|
||||
$this->unifiedData = new UnifiedScrmData();
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
// 1. 创建临时 Cookie 文件
|
||||
$this->cookieFile = tempnam(sys_get_temp_dir(), 'spider_cookie_');
|
||||
if ($this->cookieFile === false) {
|
||||
throw new \RuntimeException("无法在系统临时目录创建 Cookie 文件");
|
||||
}
|
||||
|
||||
// 2. 初始化 cURL 并设置全局参数
|
||||
$this->ch = curl_init();
|
||||
|
||||
$apiUrl = '/share/share/api_yinliu_count.html?page=1&limit=10&id=&class_id=&is_repet=1&start_time=&end_time=';
|
||||
|
||||
$defaultOptions = [
|
||||
CURLOPT_RETURNTRANSFER => true, // 将结果返回为字符串
|
||||
CURLOPT_HEADER => false, // 不输出响应头
|
||||
CURLOPT_TIMEOUT => 15, // 设置超时时间(秒)
|
||||
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
|
||||
// 核心优化:同时指定读写 Cookie 为同一个文件,cURL 会自动维护会话
|
||||
CURLOPT_COOKIEJAR => $this->cookieFile,
|
||||
CURLOPT_COOKIEFILE => $this->cookieFile,
|
||||
];
|
||||
|
||||
curl_setopt_array($this->ch, $defaultOptions);
|
||||
|
||||
$this->authenticate();
|
||||
$first_page_data = $this->fetchApiData($apiUrl); // 首页数据
|
||||
$this->unifiedData->total = $first_page_data['count']; // 总在线人数
|
||||
$this->unifiedData->todayNewCount = $first_page_data['totalRow']['day_sum']; // 今日新增在线人数
|
||||
|
||||
$total_pages = ceil($this->unifiedData->total/10); // 总页数
|
||||
$allListPagesData = [$first_page_data['data']]; // 初始化列表容器,装入第一页数据
|
||||
for ($page = 2; $page <= $total_pages; $page++) {
|
||||
$apiUrl = '/share/share/api_yinliu_count.html?page=' . $page . '&limit=10&id=&class_id=&is_repet=1&start_time=&end_time=';
|
||||
|
||||
$page_data = $this->fetchApiData($apiUrl);
|
||||
|
||||
$allListPagesData[] = $page_data['data'];
|
||||
}
|
||||
|
||||
return $this->parseToUnifiedData($first_page_data, $allListPagesData);
|
||||
}
|
||||
|
||||
// 清爽至极的数据清洗:详情是详情,列表是列表
|
||||
protected function parseToUnifiedData($detailData, $allListPagesData)
|
||||
{
|
||||
$unifiedData = $this->unifiedData;
|
||||
|
||||
// 循环合并了所有页数的 List 数组
|
||||
foreach ($allListPagesData as $records) {
|
||||
foreach ($records as $item) {
|
||||
if(!empty($item['user'])) {
|
||||
$number = $item['user'] ?? null;
|
||||
$isOnline = (isset($item['online']) && $item['online'] == 1);
|
||||
|
||||
$unifiedData->addNumber($number, $isOnline, $item['day_sum']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $unifiedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 析构函数:释放资源,清理垃圾
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// 关闭 cURL 会话
|
||||
if (is_resource($this->ch) || $this->ch instanceof \CurlHandle) {
|
||||
curl_close($this->ch);
|
||||
}
|
||||
|
||||
// 删除临时 Cookie 文件
|
||||
if (file_exists($this->cookieFile)) {
|
||||
unlink($this->cookieFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 第一步:访问授权页面,建立会话
|
||||
*
|
||||
* @param string $authUrl 包含 token 的授权地址
|
||||
* @return bool 授权请求是否成功
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function authenticate()
|
||||
{
|
||||
$this->sendRequest($this->pageUrl);
|
||||
return true; // 如果没有抛出异常,则认为请求成功
|
||||
}
|
||||
|
||||
/**
|
||||
* 第二步:请求 API 接口获取数据
|
||||
*
|
||||
* @param string $apiUrl 接口数据地址
|
||||
* @return array|null 解析后的数组数据,如果解析失败返回 null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function fetchApiData($apiUrl)
|
||||
{
|
||||
$response = $this->sendRequest($this->baseUrl . $apiUrl);
|
||||
|
||||
// 尝试解析 JSON 数据
|
||||
$data = json_decode($response, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new \RuntimeException("JSON 解析失败: " . json_last_error_msg() . "。原始响应: " . $response);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 cURL 请求的底层私有方法
|
||||
*
|
||||
* @param string $url 目标地址
|
||||
* @return string 服务器响应内容
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function sendRequest($url)
|
||||
{
|
||||
curl_setopt($this->ch, CURLOPT_URL, $url);
|
||||
|
||||
$response = curl_exec($this->ch);
|
||||
|
||||
// 检查是否有网络或 cURL 底层错误
|
||||
if ($response === false) {
|
||||
$error = curl_error($this->ch);
|
||||
throw new \RuntimeException("请求失败 [{$url}]: {$error}");
|
||||
}
|
||||
|
||||
// 检查 HTTP 状态码
|
||||
$httpCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
|
||||
if ($httpCode >= 400) {
|
||||
throw new \RuntimeException("HTTP 请求异常 [{$url}],状态码: {$httpCode}");
|
||||
}
|
||||
|
||||
return (string)$response;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+98
-28
@@ -1,15 +1,86 @@
|
||||
<?php
|
||||
// 文件名: run.php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 'ON');
|
||||
|
||||
require_once __DIR__ . '/A2c.php'; // A2c云控
|
||||
require_once __DIR__ . '/Xinghe.php'; // 星河云控
|
||||
// 文件名: run.php
|
||||
require_once __DIR__ . '/Chatknow.php'; // ChatKnow SCRM
|
||||
require_once __DIR__ . '/A2c.php'; // A2c云控
|
||||
require_once __DIR__ . '/Xinghe2.php'; // 星河云控
|
||||
require_once __DIR__ . '/Huojian.php'; // 火箭
|
||||
require_once __DIR__ . '/SsCustomer.php'; // SS云控(Customer)
|
||||
require_once __DIR__ . '/SsCustomer.php'; // SS云控(Customer)
|
||||
require_once __DIR__ . '/Haiwang.php'; // 海王
|
||||
require_once __DIR__ . '/Whatshub.php'; // Whatshub 工单平台
|
||||
|
||||
try {
|
||||
/*
|
||||
命令行可以测试Cloudflare防火墙
|
||||
curl -s -X POST http://127.0.0.1:3001/api/auth-and-intercept \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"pageUrl": "https://web.whatshub.cc/m/iTYsWKQH5030/1",
|
||||
"apiUrls": ["/api/whatshub-counter/workShare/open/detail"],
|
||||
"authActions": [
|
||||
{"type": "vue_fill", "selector": ".el-input__inner", "value": "745030"},
|
||||
{"type": "wait", "ms": 500},
|
||||
{"type": "vue_click", "selector": ".vxe-button-group .theme--primary"},
|
||||
{"type": "wait", "ms": 2200}
|
||||
],
|
||||
"antiBot": {
|
||||
"enabled": true,
|
||||
"profile": "real",
|
||||
"turnstile": true,
|
||||
"solverFallback": true,
|
||||
"sessionKey": "whatshub:t.flowerbells.top",
|
||||
"challengeTimeoutMs": 60000
|
||||
}
|
||||
}' | jq .
|
||||
*/
|
||||
|
||||
echo "🚀 开始执行<Whatshub 工单平台>抓取任务 (多引擎智能调度)...\n\r";
|
||||
$pageUrl = 'https://web.whatshub.cc/m/iTYsWKQH5030/1'; // PageUrl 入口授权页
|
||||
$username = ""; // 登录账号
|
||||
$password = "745030"; // 登录密码
|
||||
$spider = new Whatshub($pageUrl, $username, $password);
|
||||
$finalData = $spider->run();
|
||||
|
||||
echo "✅ 任务完成!统一数据如下:\n\r";
|
||||
echo "----------------------------------------\n\r";
|
||||
echo "当日新增:{$finalData->todayNewCount} 人\n\r";
|
||||
echo "在线号码:{$finalData->totalOnline} 个\n\r";
|
||||
echo "离线号码:{$finalData->totalOffline} 个\n\r";
|
||||
echo "Total:" . $finalData->total . " 个号码\n\r";
|
||||
echo "实际总共抓取:" . count($finalData->numbers) . " 个号码\n\r";
|
||||
echo "号码列表:\n\r";
|
||||
echo dd($finalData->numbers);
|
||||
} catch (Exception $e) {
|
||||
echo "🚨 抓取异常:" . $e->getMessage() . "\n\r";
|
||||
}
|
||||
|
||||
|
||||
// try {
|
||||
// echo "🚀 开始执行<ChatKnow SCRM>抓取任务 (多引擎智能调度)...\n\r";
|
||||
// $pageUrl = 'https://user.chatknow.com/child/workorder-share?shareKey=jf5t6MNrJ2mC76N'; // PageUrl 入口授权页
|
||||
// $username = ""; // 登录账号
|
||||
// $password = ""; // 登录密码
|
||||
// $spider = new Chatknow($pageUrl, $username, $password);
|
||||
// $finalData = $spider->run();
|
||||
|
||||
// echo "✅ 任务完成!统一数据如下:\n\r";
|
||||
// echo "----------------------------------------\n\r";
|
||||
// echo "当日新增:{$finalData->todayNewCount} 人\n\r";
|
||||
// echo "在线号码:{$finalData->totalOnline} 个\n\r";
|
||||
// echo "离线号码:{$finalData->totalOffline} 个\n\r";
|
||||
// echo "Total:" . $finalData->total . " 个号码\n\r";
|
||||
// echo "实际总共抓取:" . count($finalData->numbers) . " 个号码\n\r";
|
||||
// echo "号码列表:\n\r";
|
||||
// echo dd($finalData->numbers);
|
||||
// } catch (Exception $e) {
|
||||
// echo "🚨 抓取异常:" . $e->getMessage() . "\n\r";
|
||||
// }
|
||||
|
||||
// try {
|
||||
// echo "🚀 开始执行<A2c云控>抓取任务 (多引擎智能调度)...\n\r";
|
||||
// $pageUrl = 'https://user.a2c.chat/visitors/counter/share?id=33e449dc83c24ee59275bf03a2d82234'; // PageUrl 入口授权页
|
||||
// $pageUrl = 'https://yyk.ink/8415O53'; // PageUrl 入口授权页
|
||||
// $username = ""; // 登录账号
|
||||
// $password = ""; // 登录密码
|
||||
// $spider = new A2c($pageUrl, $username, $password);
|
||||
@@ -31,7 +102,7 @@ require_once __DIR__ . '/Haiwang.php'; // 海王
|
||||
|
||||
// try {
|
||||
// echo "🚀 开始执行<星河云控>抓取任务 (多引擎智能调度)...\n\r";
|
||||
// $pageUrl = 'http://103.251.112.35:10158/share/share/index.html?token=pds65jl202t2kjis5firb8epu4d8a83ptfhc63d89l3mv11nwa'; // PageUrl 入口授权页
|
||||
// $pageUrl = 'http://8.218.14.51/share/share/index.html?token=hn6z3egq4nnnebkv4063pcdouzr4ug5js902mlqo2n3yp9gzhe'; // PageUrl 入口授权页
|
||||
// $username = ""; // 登录账号
|
||||
// $password = ""; // 登录密码
|
||||
// $spider = new Xinghe($pageUrl, $username, $password);
|
||||
@@ -46,16 +117,15 @@ require_once __DIR__ . '/Haiwang.php'; // 海王
|
||||
// echo "实际总共抓取:" . count($finalData->numbers) . " 个号码\n\r";
|
||||
// echo "号码列表:\n\r";
|
||||
// echo dd($finalData->numbers);
|
||||
|
||||
// } catch (Exception $e) {
|
||||
// echo "🚨 抓取异常:" . $e->getMessage() . "\n\r";
|
||||
// }
|
||||
|
||||
// try {
|
||||
// echo "🚀 开始执行<火箭工单>抓取任务 (多引擎智能调度)...\n\r";
|
||||
// $pageUrl = 'https://s.url99.me/ygn9zjr8'; // PageUrl 入口授权页
|
||||
// $pageUrl = 'https://s.url99.me/68vfje8m'; // PageUrl 入口授权页
|
||||
// $username = ""; // 登录账号
|
||||
// $password = "123456"; // 登录密码
|
||||
// $password = "542187"; // 登录密码
|
||||
// $spider = new Huojian($pageUrl, $username, $password);
|
||||
// $finalData = $spider->run();
|
||||
|
||||
@@ -96,27 +166,27 @@ require_once __DIR__ . '/Haiwang.php'; // 海王
|
||||
// echo "🚨 抓取异常:" . $e->getMessage() . "\n\r";
|
||||
// }
|
||||
|
||||
try {
|
||||
echo "🚀 开始执行<海王>抓取任务 (多引擎智能调度)...\n\r";
|
||||
$pageUrl = 'https://admin.haiwangweb.com/web#/accountshow/pZsEulYrb'; // PageUrl 入口授权页
|
||||
$username = ""; // 登录账号
|
||||
$password = "9999"; // 登录密码
|
||||
$spider = new Haiwang($pageUrl, $username, $password);
|
||||
$finalData = $spider->run();
|
||||
// try {
|
||||
// echo "🚀 开始执行<海王>抓取任务 (多引擎智能调度)...\n\r";
|
||||
// $pageUrl = 'https://admin.haiwangweb.com/web#/accountshow/pZsEulYrb'; // PageUrl 入口授权页
|
||||
// $username = ""; // 登录账号
|
||||
// $password = "9999"; // 登录密码
|
||||
// $spider = new Haiwang($pageUrl, $username, $password);
|
||||
// $finalData = $spider->run();
|
||||
|
||||
echo "✅ 任务完成!统一数据如下:\n\r";
|
||||
echo "----------------------------------------\n\r";
|
||||
echo "当日新增:{$finalData->todayNewCount} 人\n\r";
|
||||
echo "在线号码:{$finalData->totalOnline} 个\n\r";
|
||||
echo "离线号码:{$finalData->totalOffline} 个\n\r";
|
||||
echo "Total:" . $finalData->total . " 个号码\n\r";
|
||||
echo "实际总共抓取:" . count($finalData->numbers) . " 个号码\n\r";
|
||||
echo "号码列表:\n\r";
|
||||
echo dd($finalData->numbers);
|
||||
// echo "✅ 任务完成!统一数据如下:\n\r";
|
||||
// echo "----------------------------------------\n\r";
|
||||
// echo "当日新增:{$finalData->todayNewCount} 人\n\r";
|
||||
// echo "在线号码:{$finalData->totalOnline} 个\n\r";
|
||||
// echo "离线号码:{$finalData->totalOffline} 个\n\r";
|
||||
// echo "Total:" . $finalData->total . " 个号码\n\r";
|
||||
// echo "实际总共抓取:" . count($finalData->numbers) . " 个号码\n\r";
|
||||
// echo "号码列表:\n\r";
|
||||
// echo dd($finalData->numbers);
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "🚨 抓取异常:" . $e->getMessage() . "\n\r";
|
||||
}
|
||||
// } catch (Exception $e) {
|
||||
// echo "🚨 抓取异常:" . $e->getMessage() . "\n\r";
|
||||
// }
|
||||
|
||||
// try {
|
||||
// echo "🚀 开始执行<CEO SCRM>抓取任务 (多引擎智能调度)...\n\r";
|
||||
|
||||
Reference in New Issue
Block a user