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);
}
});
또한 라즈베리 파이에 배포하는 방법에 대한 요점 을 작성했습니다 . 작동하므로 개선 방법에 대한 제안을 크게 주시면 감사하겠습니다.
광범위한 스트로크에서이 프로그램 :
- 메시지 수신
- 메시지 유효성 검사
- 메시지 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);
}
}
```