d20pfsrd Discord Bot Scraper Абстракция и развертывание
Я написал бота Discord, который прослушивает ссылки на книгу правил d20pfsrd в чате Discord, проверяет, являются ли они подвигами или магией, а затем очищает страницу, форматирует ее и выводит обратно в чат как форматированный текст. Страницы, которые я проверяю, достаточно шаблонны, поэтому, хотя используемые мной селекторы Cheerio, вероятно, довольно хрупкие, в большинстве случаев это работает. Тем не менее, средства форматирования текста - некоторые уродливые твари (хотя логика, вероятно, уникальна), и вызовы axios также могут нуждаться в некоторой очистке.
Моя проблема заключается в следующем: я подозревал, что около 40% кода можно реорганизовать, если я правильно обобщу его. Мое решение заключалось в том, чтобы сделать что-то, что, вероятно, можно было бы описать как злоупотребление оператором распространения:
async function getPage(msg, url){
let message = "placeholder";
await axios.get(url).then( (response) => {
message = responder(...selectResponder(url), response);
}
).catch((error) => {
console.error(error.message);
});
sendMessage(message, msg);
}
Через неделю я понимаю, что написал функции таким образом, чтобы они читались в обратном порядке? Если оставить в стороне эстетику, вот как это работает:
function selectResponder(siteUrl){
if (siteUrl.startsWith("https://www.d20pfsrd.com/feats/")){
return feats.featsConfig;
} else if (siteUrl.startsWith("https://www.d20pfsrd.com/magic/")){
return magic.magicConfig;
}
}
function responder(parser, formatter, messageFormatter, response){
const replyData = parser(response.data);
const formattedData = formatter(replyData);
return messageFormatter(formattedData);
}
Идея состоит в том, что в magic.js и feats.js существует как можно больше уникальной логики, насколько это возможно. Как мне очистить этот раздел? Репозиторий github здесь, и я хотел бы получить отзывы обо всем проекте. Я сделал большую часть этого, потому что считал странным иметь здесь большой блок if и дублировать вызовы axios:
client.on('message', msg => {
if(validateUrl(msg.content)){
const siteUrl = encodeURI(msg.content);
getPage(msg, siteUrl);
}
});
Также я написал эту суть о том, как я развернул его на Raspberry Pi. Это работает, поэтому мы будем очень признательны за предложения по его улучшению.
В общих чертах эта программа:
- Слушает сообщение
- Проверяет сообщение
- Получает содержимое страницы по URL-адресу сообщения
- Анализирует содержимое страницы
- Переформатирует содержимое страницы
- Преобразует содержимое страницы в сообщение
- Отправляет сообщение
Ответы
Вот как бы я это сделал. Перенесите логику, определяющую, какие страницы анализатор использует, в код этого парсера. Кроме того, организация ваших вспомогательных файлов в объекты может снизить сложность с точки зрения количества переменных, которые вы передаете, но это больше вопрос личных предпочтений.
class SpecificPageParser {
match(url) {
return (
url.startswith('https://www.d20pfsrd.com/magic/') &&
!url.endsWith('/magic/')
);
}
format(response) {
// do your parsing stuff
const formatted = {...response,'extra':'info'};
return formatted;
}
}
const responders = [new SpecificPageParser(),new SomeOtherParser()];
async function getPage(msg, url){
try {
const responder = responders.find(responder=>responder.match(url));
if (!responder) return;
const response = await axios.get(url);
const message = responder.format(response);
sendMessage(message, msg);
}
catch(error) {
console.error(error);
}
}
```