Я пытаюсь получить данные из API, но он каким-то образом получает странные данные, я пробовал много вещей и не знаю, что еще я мог бы сделать.

const https = require("https");
https.get(`https://drednot.io/api/scoreboard?count=1000&offset_score=-1`, (resp) => {
    let data = '';
    resp.on('data', (chunk) => {
        data += chunk;
    });
    resp.on('end', async () => {
        try {
            //console.log(data)
            let result = JSON.parse(data.toString())["ships"];
            console.log(result)
        } catch (err) {
            console.log("Error: " + err.message);
        }
    });
}).on("error", async (err) => {
    console.log("Error: " + err.message);
});

Как необработанные данные, так и проанализированные данные содержат какие-то странные вещи внутри них, например, подстроку в необработанных данных

{"sh         ip_name":"⚜️ Full Farm Barn","hex_code":"20DE1","color":9079434,"score":2395790}

Или часть проанализированных данных (отличается, потому что по какой-то причине приведенное выше не находится внутри анализируемых данных)

{
    ship_name: '�������� '        ,
    hex_code: '78AD5F',
    color: 815352,
    score: 25915190
}

Изменить: символы � анализируются правильно, они просто не могут отображаться терминалом, что не является проблемой.

Полный код, чтобы понять, что я имею в виду, иногда он должен печатать изменения, но он печатает изменения все время, что неверно:

const https = require("https");


function sleep(ms) {
    if (ms <= 0) {

    } else {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

var shipData = {};
class Syncer {
    finished;
    round_fetch;
    round_error;

    constructor() {
        this.finished = true;
        this.round_fetch = 0;
        this.round_error = 0;
    }

    fetch_data(offset_score, next_request, recursion_deep) {
        //console.log(offset_score)
        this.round_fetch += 1;

        https.get(`https://drednot.io/api/scoreboard?count=1000&offset_score=${offset_score.toString()}`, (resp) => {
            let chunks = [];
            resp.on('data', (chunk) => {
                chunks.push(chunk);
            });

            resp.on('end', async () => {
                let end = Date.now();
                try {
                    //console.log(data)
                    let data = Buffer.concat(chunks).toString('utf8');
                    //console.log(data)
                    console.log(`Index of hexcode: ${data.search("32FF2B")}`)
                    let result = JSON.parse(data)["ships"];
                    data = null;
                    let next_offset = result[result.length - 1].score;
                    if (next_offset === offset_score) {
                        next_offset -= 1;
                    }
                    if (next_offset < 10000000) {
                        next_offset = -1;
                    }
                    if (next_offset !== -1) {
                        if (end < next_request) {
                            await sleep(next_request - end);
                        }
                        this.fetch_data(next_offset, Date.now() + 100, recursion_deep + 1);
                    } else {
                        this.finished = true;
                    }
                    next_offset = null;
                    let rank = (recursion_deep * 1000) + 1;

                    for (let ship of result) {
                        await sleep(1);
                        ship["rank"] = rank;
                        if (ship.hex_code === "32FF2B") {
                            console.log(`Parsed ship: ${ship}`)
                        }
                        if (shipData[ship.hex_code] !== undefined) {
                            this.checkChange(shipData[ship.hex_code], ship);
                        }
                        shipData[ship.hex_code] = ship;
                    }
                    result = null;
                    offset_score = null;
                } catch (err) {
                    console.log("Error: " + err.message);
                    await sleep(1000);
                    this.round_error += 1;
                    await this.fetch_data(offset_score, Date.now() + 100, recursion_deep);
                }
            });
        }).on("error", async (err) => {
            console.log("Error: " + err.message);
            await sleep(1000);
            this.round_error += 1;
            await this.fetch_data(offset_score, Date.now() + 100, recursion_deep);
        });
    }
    checkChange(oldShip, newShip) {

        // CHECK IF OLD NAME ISNT THE SAME AS THE NEW ONE, IF SO PRINT CHANGE
        if (oldShip.ship_name !== newShip.ship_name) {
            console.log(`${oldShip.ship_name} | ${newShip.ship_name}`)
        }
    }


    async launch() {
        //this.postChanges();
        while (true) {
            try {
                if (this.finished) {
                    this.finished = false;
                    console.log(`Fetch all ships, fetch ${this.round_fetch}, error ${this.round_error}`);
                    this.round_error = 0;
                    this.round_fetch = 0;
                    await sleep(100);
                    this.fetch_data(-1, Date.now() + 100, 0);
                }
                await sleep(1000);
            } catch (e) {
                console.log(e);
            }
        }
    }
}

function launch() {
    // Start the servers
    var synchro = new Syncer();
    synchro.launch()
}

launch()
-2
Gravity Assist 18 Ноя 2021 в 17:27
Возможно, мне придется сказать, что результат для каждого запроса разный, если вы не понимаете, что я имею в виду, используйте цикл и сравните результаты.
 – 
Gravity Assist
18 Ноя 2021 в 17:33
Ваш терминал не поддерживает 𝗣𝗮𝗿𝗮𝗱𝗶𝘀𝗲. Это не ASCII. Мой терминал поддерживает это, но выглядит странно. 𝗣𝗮𝗿𝗮𝗱𝗶𝘀𝗲 не является Paradise. Это разные персонажи.
 – 
jabaa
18 Ноя 2021 в 17:45
Дело не в раю, а в таких местах, как здесь "col or"
 – 
Gravity Assist
18 Ноя 2021 в 17:48
1
Основная проблема - это отсутствие минимального воспроизводимого примера. Ваш пример требует сетевого взаимодействия и не воспроизводится. Вы должны добавить два ответа на свой вопрос и удалить сетевое соединение. Сократите свой код до точной задачи.
 – 
jabaa
18 Ноя 2021 в 18:40

1 ответ

Лучший ответ

Проблема может заключаться в том, что прибывшие многобайтовые последовательности разбиты на разные части, и нет смысла превращать какой-либо отдельный фрагмент в строку отдельно, потому что некоторые байты символа находятся в одном фрагменте, а другие байты этот символ находится в следующем фрагменте.

Чтобы обойти это, просто накапливайте блоки входящих данных, сохраняя буферы, в которые они изначально поступили, и объедините все буферы (блоки) в один буфер перед преобразованием их в строку.

Вместо data = '' сделайте chunks = [], а вместо data += chunk; сделайте chunks.push(chunk), а затем в обработчике 'end' сделайте data = Buffers.concat(chunks).toString('utf8').

    let chunks = [];
    resp.on('data', (chunk) => {
        chunks.push(chunk);
    });
    resp.on('end', async () => {
        let data = Buffer.concat(chunks).toString('utf8');
        try {
            //console.log(data)
            let result = JSON.parse(data.toString())["ships"];
            console.log(result)
        } catch (err) {
            console.log("Error: " + err.message);
        }
    });
1
Wyck 18 Ноя 2021 в 18:07
Я пробовал это, проблема все еще возникает.
 – 
Gravity Assist
18 Ноя 2021 в 18:12
1
Помимо повторной переустановки узла, это сработало.
 – 
Gravity Assist
18 Ноя 2021 в 18:50