Я пытаюсь получить данные из 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()
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);
}
});
Похожие вопросы
Связанные вопросы
Новые вопросы
node.js
Node.js — это основанная на событиях, неблокирующая, асинхронная среда выполнения ввода-вывода, использующая движок Google V8 JavaScript и библиотеку libuv. Он используется для разработки приложений, которые интенсивно используют возможность запуска JavaScript как на стороне клиента, так и на стороне сервера и, следовательно, выигрывают от возможности повторного использования кода и отсутствия переключения контекста.
𝗣𝗮𝗿𝗮𝗱𝗶𝘀𝗲
. Это не ASCII. Мой терминал поддерживает это, но выглядит странно.𝗣𝗮𝗿𝗮𝗱𝗶𝘀𝗲
не являетсяParadise
. Это разные персонажи."col or"