d20pfsrd Discord Bot Scraper 추상화 및 배포

Aug 16 2020

나는 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);
  }
  

});

또한 라즈베리 파이에 배포하는 방법에 대한 요점 을 작성했습니다 . 작동하므로 개선 방법에 대한 제안을 크게 주시면 감사하겠습니다.

광범위한 스트로크에서이 프로그램 :

  1. 메시지 수신
  2. 메시지 유효성 검사
  3. 메시지 URL에서 페이지 콘텐츠를 가져옵니다.
  4. 페이지 콘텐츠를 구문 분석합니다.
  5. 페이지 콘텐츠의 형식을 다시 지정합니다.
  6. 페이지 내용을 메시지로 변환
  7. 메시지를 보냅니다.

답변

1 TedBrownlow Aug 16 2020 at 10:57

내가 할 방법은 다음과 같습니다. 파서가 소비하는 페이지에 대한 논리를 해당 파서의 코드로 이동합니다. 또한 도우미 파일을 개체로 구성하면 전달하는 변수 수의 복잡성을 줄일 수 있지만 이는 개인적인 선호도의 문제입니다.

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);
    }
  }
```