andtun

andtun

[php] APEX排行榜爬虫API

140
2024-02-17
[php] APEX排行榜爬虫API

特点:

  • 数据缓存,避免每次访问api都去爬一次

  • token验证,避免被盗链

  • MySQL数据库数据支持

代码:

<?php
// 检查是否存在所有必需的 POST 参数
if (!isset($_POST['token'])) {
    http_response_code(400);
    die("警告:非法请求链接");
}

// 验证令牌
$token = $_POST['token'];
if ($token !== "your-token") {
    http_response_code(401);
    die("无效的令牌");
}

// 连接数据库
$servername = "mysql:3306";
$username = "user";
$password = "password";
$dbname = "database";

$conn = new mysqli($servername, $username, $password, $dbname);

// 检查连接
if ($conn->connect_error) {
    http_response_code(500);
    die("连接失败: " . $conn->connect_error);
}

// 查询白名单
$whitelist = array();
$sql_whitelist = "SELECT id,name FROM whitelist";
$result_whitelist = $conn->query($sql_whitelist);

if ($result_whitelist->num_rows > 0) {
    while($row = $result_whitelist->fetch_assoc()) {
        $whitelist[] = array(
            "id" => $row["id"],
            "name" => $row["name"]
        );
    }
}

// 查询黑名单
$blacklist = array();
$sql_blacklist = "SELECT id,name,reason FROM blacklist";
$result_blacklist = $conn->query($sql_blacklist);

if ($result_blacklist->num_rows > 0) {
    while($row = $result_blacklist->fetch_assoc()) {
        $blacklist[] = array(
            "id" => $row["id"],
            "name" => $row["name"],
            "reason" => $row["reason"]
        );
    }
}

// 缓存时间:8小时
$cache_time = 28800;

if (file_exists('ranklist.json')) {
    $timestamp = filemtime('ranklist.json');
    if (time() - $timestamp < $cache_time) { // 时间戳差小于缓存时间,从本地加载数据
        $ranklist_json = file_get_contents('ranklist.json');
        $ranklist = json_decode($ranklist_json, true);
    } else { // 时间戳差大于等于缓存时间,返回缓存数据并更新缓存
        $ranklist_json = file_get_contents('ranklist.json');
        $ranklist = json_decode($ranklist_json, true);
        // 更新缓存
        $updated_ranklist = fetchRanklist();
        if (!empty($updated_ranklist)) {
            $ranklist = $updated_ranklist;
            file_put_contents('ranklist.json', json_encode($ranklist));
        }
    }
} else { // 本地没有保存的排行榜数据,查询数据并保存到本地
    $ranklist = fetchRanklist();
    file_put_contents('ranklist.json', json_encode($ranklist));
}

// 查询排行榜函数
function fetchRanklist() {
    $ranklist = array(); // 初始化 $ranklist 数组

    $url = "https://apexlegendsstatus.com/live-ranked-leaderboards/Battle_Royale/PC";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36");
    $response = curl_exec($ch);
    curl_close($ch);

    if ($response !== false) {
        $dom = new DOMDocument();
        libxml_use_internal_errors(true);
        $dom->loadHTML($response);
        libxml_clear_errors();

        $xpath = new DOMXPath($dom);
        $userModules = $xpath->query('//a[@target="_alsLeaderboard"]');
        $rankModules = $xpath->query('//b');

        $count = 0;

        foreach ($userModules as $index => $userModule) {
            $rankText = $rankModules[$index]->textContent;
            if (strpos($rankText, "Player missing") === false) {
                $link = $userModule->getAttribute('href');
                $userId = substr($link, strrpos($link, '/') + 1);
                $username = $userModule->textContent;
                $rank = $rankText;

                $user = [
                    "id" => $userId,
                    "name" => $username,
                    "rank" => intval($rank)
                ];

                $ranklist[] = $user; // 直接将用户数据添加到 $ranklist 数组中

                $count++;
                if ($count >= 700) { // 爬取数量
                    break;
                }
            }
        }
    }

    return $ranklist;
}

// 构建响应数据
$response = array(
    "update" => date("Y-m-d H:i:s"),
    "whitelist" => $whitelist,
    "blacklist" => $blacklist,
    "ranklist" => $ranklist
);

// 返回JSON响应
header('Content-Type: application/json');
echo json_encode($response);

// 关闭连接
$conn->close();

客户端代码:

语言:C++ 20,需要用到库:httplib.h

void Server::UpdateList()
{
    // 准备要发送的数据
    std::string data = "token=" + std::string(TOKEN);

    // 发送 POST 请求
    const char *url = "/";
    auto res = client.Post(url, data.c_str(), "application/x-www-form-urlencoded");
    if (res && res->status == 200)
    {
        // 解析 JSON 数据
        cJSON *root = cJSON_Parse(res->body.c_str());
        if (root != NULL)
        {
            // 解析白名单数组
            parseList(root, "whitelist", &vars.whitelist, 20);

            // 解析黑名单数组
            parseList(root, "blacklist", &vars.blacklist, 100);

            // 解析排行榜数组
            parseList(root, "ranklist", &vars.ranklist, 300);
            
            cJSON_Delete(root);
        }
    }
    else
    {
        printf("[服务器] 更新[白名单][黑名单][猎杀Top700名单]列表 - 失败\n");
    }
}