search.js 8.08 KB
const Discord = require("discord.js");
exports.run = async (client, msg, args, prefix) => {
    if (args[0]) { // 명령어 뒤에 입력값이 있을 경우 (ex. !<명령어> <채팅>)
        // 검색어 한 문장으로 합치기
        const search = args.join(' ');
        // console.log(search);

        // 각 사이트별 제품 검색        
        const puppeteer = require('puppeteer'); //include Puppeteer Library
        puppeteer.launch({headless:true}).then(async browser => {
            // 브라우저 열기
            const page = await browser.newPage();
            console.log('Open Browser');
           
            // 1. 베스트펜
            try {
                console.log("bestpen crawling");
                await page .goto('http://www.bestpen.kr');

                // 검색창으로 이동 & search 검색
                await page.waitForSelector('#header > div.headerBtm > div > p.searchOpen > i');
                await page .click('#header > div.headerBtm > div > p.searchOpen > i');
                await page .type('#keyword', search);
                await page .keyboard.press( "Enter" );
                // await page.screenshot({ path : "screenshot.png" });
            } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지

            // 검색 결과 가져오기 (최대 4개)
            var bestpen = '';
            for (var i = 1; i <= 4; i++) {
                try {
                    var title = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a');
                    var bestpen_title = await page.evaluate( title => title.textContent, title );
                    // console.log("베스트펜 검색 결과 제품명 : ", bestpen_title);
        
                    var link = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dt > a');
                    var bestpen_link = await page.evaluate( link => link.href, link );
                    // console.log("베스트펜 검색 링크 : ", bestpen_link);

                    // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
                    // -> 글자수 제한(1024)도 있으므로 제거
                    bestpen_link = bestpen_link.slice(0, bestpen_link.indexOf('&search'));
                    
                    try {
                        var price = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-price > p:nth-child(2) > span.price');
                        var bestpen_data = await page.evaluate( price => price.textContent, price );
                        // console.log("베스트펜 검색 결과 가격 : ", bestpen_data);
                    } catch {
                        // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
                        bestpen_data = "SOLD OUT";
                    }

                    bestpen += `[${bestpen_title}](${bestpen_link}) - ${bestpen_data}` + '\n';
                } catch {
                    if (i == 1) {
                        // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
                        bestpen += "검색결과 없음" + '\n';
                        break;
                    } else {
                        // 제품 개수가 4개 이하인 경우
                        break;
                    }
                }
            }

            // 2. 펜카페
            try {
                console.log("pencafe crawling");
                await page .goto('http://www.pencafe.co.kr');

                // search 검색
                await page.waitForSelector('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input');
                await page .type('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input', search);
                await page .keyboard.press( "Enter" );
                // await page.screenshot({ path : "screenshot.png" });
            } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지

            // 검색 결과 가져오기 (최대 4개)
            var pencafe = '';
            for (var i = 1; i <= 4; i++) {
                try {
                    var title = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a');
                    var pencafe_title = await page.evaluate( title => title.textContent, title );
                    // console.log("펜카페 검색 결과 제품명 : ", pencafe_title);

                    // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거
                    if (pencafe_title.indexOf('%') != -1) { pencafe_title = pencafe_title.slice(pencafe_title.indexOf('%')+1); }
                    // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거
                    if (pencafe_title.indexOf('(') != -1) { pencafe_title = pencafe_title.slice(0, pencafe_title.lastIndexOf('(')); }
        
                    var link = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a');
                    var pencafe_link = await page.evaluate( link => link.href, link );
                    // console.log("펜카페 검색 링크 : ", pencafe_link);

                    // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
                    // -> 글자수 제한(1024)도 있으므로 제거
                    pencafe_link = pencafe_link.slice(0, pencafe_link.indexOf('&search'));
                    
                    try {
                        var price = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-price > span');
                        var pencafe_data = await page.evaluate( price => price.textContent, price );
                        // console.log("펜카페 검색 결과 가격 : ", pencafe_data);
                    } catch {
                        // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
                        pencafe_data = "SOLD OUT";
                    }

                    pencafe += `[${pencafe_title}](${pencafe_link}) - ${pencafe_data}` + '\n';
                } catch {
                    if (i == 1) {
                        // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
                        pencafe += "검색결과 없음" + '\n'
                        break;
                    } else {
                        // 제품 개수가 4개 이하인 경우
                        break;
                    }
                }
            }

            // 브라우저 닫기
            await browser.close();
            console.log('Browser Closed');

            // 검색 결과 챗봇에 출력
            let Commands = new Discord.MessageEmbed()
            .setTitle(`${search}에 대한 검색 결과`)
            .setColor("E5D49A")
            // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액)
            .addField('베스트펜', `${bestpen.slice(0, 1023)}`)
            // 펜카페 검색 결과
            .addField('펜카페', `${pencafe.slice(0, 1023)}`)
            msg.reply({ embeds: [Commands] });
        });

        // 검색 대기 시간이 길어질 수 있으므로 사용자에게 진행상황을 알려줄 필요가 있다
        msg.reply("검색중 ...");
    } else {
        msg.reply("검색어가 없습니다. 검색어를 추가해서 다시 입력해주세요.");
    }
};

exports.config = {
    name: '문구',
    aliases: ['문구류', '가격비교', 'stationery', 'search'],
    category: ['stationery'],
    des: ['채팅 내용에 대한 검색결과를 보여줍니다.'],
    use: ['!문구 <채팅>']
};