String15

Modified to parallel processing to speed up

1 const Discord = require("discord.js"); 1 const Discord = require("discord.js");
2 exports.run = async (client, msg, args, prefix) => { 2 exports.run = async (client, msg, args, prefix) => {
3 if (args[0]) { // 명령어 뒤에 입력값이 있을 경우 (ex. !<명령어> <채팅>) 3 if (args[0]) { // 명령어 뒤에 입력값이 있을 경우 (ex. !<명령어> <채팅>)
4 - // 각 사이트별 제품 검색 4 + // 검색어 한 문장으로 합치기
5 - const puppeteer = require('puppeteer'); //include Puppeteer Library 5 + const search = args.join(' ');
6 - puppeteer.launch({headless:true}).then(async browser => { 6 + // console.log(search);
7 - // 브라우저 열기 7 +
8 + // 검색 대기 시간이 길어질 수 있으므로 사용자에게 진행상황을 알려줄 필요가 있다
9 + msg.reply("검색중 ...");
10 +
11 + //include Puppeteer Library
12 + const puppeteer = require('puppeteer');
13 +
14 + const withBrowser = async (fn) => {
15 + const browser = await puppeteer.launch({headless:true});
16 + try {
17 + return await fn(browser);
18 + } finally {
19 + await browser.close();
20 + }
21 + }
22 +
23 + const withPage = (browser) => async (fn) => {
8 const page = await browser.newPage(); 24 const page = await browser.newPage();
9 - console.log('Open Browser');
10 -
11 - // 1. 베스트펜
12 try { 25 try {
13 - console.log("bestpen crawling"); 26 + return await fn(page);
14 - await page .goto('http://www.bestpen.kr'); 27 + } finally {
28 + await page.close();
29 + }
30 + }
15 31
16 - // 검색창으로 이동 & args[0] 검색 32 + const urls = ['http://www.bestpen.kr/shop/shopbrand.html?&search=', 'http://www.pencafe.co.kr/shop/shopbrand.html?&search=', 'https://blueblack.co.kr/product/search.html?&keyword=', 'http://japan9.co.kr/shop/shopbrand.html?&search='];
17 - await page.waitForSelector('#header > div.headerBtm > div > p.searchOpen > i'); 33 + const results = await withBrowser(async (browser) => {
18 - await page .click('#header > div.headerBtm > div > p.searchOpen > i'); 34 + return Promise.all(urls.map(async (url) => {
19 - await page .type('#keyword', args[0]); 35 + return withPage(browser)(async (page) => {
20 - await page .keyboard.press( "Enter" ); 36 + // 각 사이트별 제품 검색
21 - // await page.screenshot({ path : "screenshot.png" }); 37 + var result = '';
22 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 38 + site : switch(urls.indexOf(url)) {
39 + case 0:
40 + // 베스트펜
41 + try {
42 + var bestpen_url = url + search + "&sort=price"
43 + await page.goto(bestpen_url);
44 + // console.log("bestpen crawling");
23 45
24 - // 검색 결과 가져오기 (최대 4개) 46 + // 페이지 로딩 대기
25 - var bestpen = ''; 47 + await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a');
26 - for (var i = 1; i <= 4; i++) { 48 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
27 - try {
28 - var title = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a');
29 - var bestpen_title = await page.evaluate( title => title.textContent, title );
30 - // console.log("베스트펜 검색 결과 제품명 : ", bestpen_title);
31 -
32 - var link = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dt > a');
33 - var bestpen_link = await page.evaluate( link => link.href, link );
34 - // console.log("베스트펜 검색 링크 : ", bestpen_link);
35 49
36 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 50 + // 검색 결과 가져오기 (최대 4개)
37 - // -> 글자수 제한(1024)도 있으므로 제거 51 + searchLoop : for (var i = 1; i <= 4; i++) {
38 - bestpen_link = bestpen_link.slice(0, bestpen_link.indexOf('&search')); 52 + try {
53 + var title = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a', element => {
54 + return element.textContent;
55 + });
56 + // console.log("베스트펜 검색 결과 제품명 : ", title);
39 57
40 - try { 58 + var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dt > a', element => {
41 - 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'); 59 + return element.href;
42 - var bestpen_data = await page.evaluate( price => price.textContent, price ); 60 + });
43 - // console.log("베스트펜 검색 결과 가격 : ", bestpen_data); 61 + // console.log("베스트펜 검색 링크 : ", link);
44 - } catch {
45 - // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
46 - bestpen_data = "SOLD OUT";
47 - }
48 -
49 - bestpen += `[${bestpen_title}](${bestpen_link}) - ${bestpen_data}` + '\n';
50 - } catch {
51 - if (i == 1) {
52 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
53 - bestpen += "검색결과 없음" + '\n';
54 - break;
55 - } else {
56 - // 제품 개수가 4개 이하인 경우
57 - break;
58 - }
59 - }
60 - }
61 62
62 - // 2. 펜카페 63 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
63 - try { 64 + // -> 글자수 제한(1024)도 있으므로 제거
64 - console.log("pencafe crawling"); 65 + link = link.slice(0, link.indexOf('&search'));
65 - await page .goto('http://www.pencafe.co.kr'); 66 +
67 + try {
68 + var price = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-price > p:nth-child(2) > span.price', element => {
69 + return element.textContent;
70 + });
71 + // console.log("베스트펜 검색 결과 가격 : ", price);
72 + } catch {
73 + // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
74 + price = "SOLD OUT";
75 + }
66 76
67 - // args[0] 검색 77 + result += `[${title}](${link}) - ${price}` + '\n';
68 - await page.waitForSelector('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input'); 78 + } catch {
69 - await page .type('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input', args[0]); 79 + if (i == 1) {
70 - await page .keyboard.press( "Enter" ); 80 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
71 - // await page.screenshot({ path : "screenshot.png" }); 81 + result += "검색결과 없음" + '\n';
72 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 82 + break searchLoop;
83 + } else {
84 + // 제품 개수가 4개 이하인 경우
85 + break searchLoop;
86 + }
87 + }
88 + }
89 + break site;
90 + case 1:
91 + // 펜카페
92 + try {
93 + var pencafe_url = url + search + "&sort=price"
94 + await page.goto(pencafe_url);
95 + // console.log("pencafe crawling");
73 96
74 - // 검색 결과 가져오기 (최대 4개) 97 + // 페이지 로딩 대기
75 - var pencafe = ''; 98 + await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a');
76 - for (var i = 1; i <= 4; i++) { 99 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
77 - try {
78 - var title = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a');
79 - var pencafe_title = await page.evaluate( title => title.textContent, title );
80 - // console.log("펜카페 검색 결과 제품명 : ", pencafe_title);
81 100
82 - // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거 101 + // 검색 결과 가져오기 (최대 4개)
83 - if (pencafe_title.indexOf('%') != -1) { pencafe_title = pencafe_title.slice(pencafe_title.indexOf('%')+1); } 102 + searchLoop : for (var i = 1; i <= 4; i++) {
84 - // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거 103 + try {
85 - if (pencafe_title.lastIndexOf(')') == pencafe_title.length-1) { pencafe_title = pencafe_title.slice(0, pencafe_title.lastIndexOf('(')); } 104 + var title = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a', element => {
86 - 105 + return element.textContent;
87 - var link = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a'); 106 + });
88 - var pencafe_link = await page.evaluate( link => link.href, link ); 107 + // console.log("펜카페 검색 결과 제품명 : ", title);
89 - // console.log("펜카페 검색 링크 : ", pencafe_link);
90 108
91 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 109 + // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거
92 - // -> 글자수 제한(1024)도 있으므로 제거 110 + if (title.indexOf('%') != -1) { title = title.slice(title.indexOf('%')+1); }
93 - pencafe_link = pencafe_link.slice(0, pencafe_link.indexOf('&search')); 111 + // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거
112 + if (title.lastIndexOf(')') == title.length-1) { title = title.slice(0, title.lastIndexOf('(')); }
94 113
95 - try { 114 + var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a', element => {
96 - var price = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-price > span'); 115 + return element.href;
97 - var pencafe_data = await page.evaluate( price => price.textContent, price ); 116 + });
98 - // console.log("펜카페 검색 결과 가격 : ", pencafe_data); 117 + // console.log("펜카페 검색 링크 : ", link);
99 - } catch {
100 - // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
101 - pencafe_data = "SOLD OUT";
102 - }
103 118
104 - pencafe += `[${pencafe_title}](${pencafe_link}) - ${pencafe_data}` + '\n'; 119 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
105 - } catch { 120 + // -> 글자수 제한(1024)도 있으므로 제거
106 - if (i == 1) { 121 + link = link.slice(0, link.indexOf('&search'));
107 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 122 +
108 - pencafe += "검색결과 없음" + '\n'; 123 + try {
109 - break; 124 + var price = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-price > span', element => {
110 - } else { 125 + return element.textContent;
111 - // 제품 개수가 4개 이하인 경우 126 + });
112 - break; 127 + // console.log("펜카페 검색 결과 가격 : ", price);
113 - } 128 + } catch {
114 - } 129 + // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시
115 - } 130 + price = "SOLD OUT";
131 + }
116 132
117 - // 3. 블루블랙 133 + result += `[${title}](${link}) - ${price}` + '\n';
118 - try { 134 + } catch {
119 - console.log("blueblack crawling"); 135 + if (i == 1) {
120 - await page .goto('https://blueblack.co.kr'); 136 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
137 + result += "검색결과 없음" + '\n';
138 + break searchLoop;
139 + } else {
140 + // 제품 개수가 4개 이하인 경우
141 + break searchLoop;
142 + }
143 + }
144 + }
145 + break site;
146 + case 2:
147 + // 블루블랙
148 + try {
149 + var blueblack_url = url + search + "&order_by=priceasc"
150 + await page.goto(blueblack_url);
151 + // console.log("blublack crawling");
121 152
122 - // args[0] 검색 153 + // 페이지 로딩 대기
123 - await page.waitForSelector('#keyword'); 154 + await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child(4) > div.description > p.name > a > span:nth-child(2)');
124 - await page .type('#keyword', args[0]); 155 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
125 - await page .keyboard.press( "Enter" );
126 - // await page.screenshot({ path : "screenshot.png" });
127 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
128 156
129 - // 검색 결과 가져오기 (최대 4개) 157 + // 검색 결과 가져오기 (최대 4개)
130 - var blueblack = ''; 158 + searchLoop : for (var i = 1; i <= 4; i++) {
131 - for (var i = 1; i <= 4; i++) { 159 + try {
132 - try { 160 + var title = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > p.name > a > span:nth-child(2)', element => {
133 - var title = await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > p.name > a > span:nth-child(2)'); 161 + return element.textContent;
134 - var blueblack_title = await page.evaluate( title => title.textContent, title ); 162 + });
135 - // console.log("블루블랙 검색 결과 제품명 : ", blueblack_title); 163 + // console.log("블루블랙 검색 결과 제품명 : ", title);
136 - 164 +
137 - var link = await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > p.name > a'); 165 + var link = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > p.name > a', element => {
138 - var blueblack_link = await page.evaluate( link => link.href, link ); 166 + return element.href;
139 - // console.log("블루블랙 검색 링크 : ", blueblack_link); 167 + });
168 + // console.log("블루블랙 검색 링크 : ", link);
140 169
141 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 170 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
142 - // -> 글자수 제한(1024)도 있으므로 제거 171 + // -> 글자수 제한(1024)도 있으므로 제거
143 - pencafe_link = pencafe_link.slice(0, pencafe_link.indexOf('&cate_no')); 172 + link = link.slice(0, link.indexOf('&cate_no'));
144 173
145 - try { 174 + try {
146 - // 품절 아이콘이 있는지 확인 175 + // 품절 아이콘이 있는지 확인
147 - await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > div.status > div > img', element => { 176 + await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > div.status > div > img', element => {
148 - return element.getAttribute("src"); 177 + return element.getAttribute("src");
149 - }); 178 + });
150 179
151 - blueblack_data = 'SOLD OUT'; 180 + var price = 'SOLD OUT';
152 - } catch { 181 + } catch {
153 - // 품절 아이콘이 없을 경우 182 + try {
154 - var price = await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > ul > li:nth-child(3) > span:nth-child(2)'); 183 + // 품절 아이콘이 없을 경우
155 - var blueblack_data = await page.evaluate( price => price.textContent, price ); 184 + var price = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > ul > li:nth-child(3) > span:nth-child(2)', element => {
156 - // console.log("블루블랙 검색 결과 가격 : ", blueblack_data); 185 + return element.textContent;
157 - } 186 + });
187 + } catch {
188 + var price = '0원';
189 + }
190 + }
191 + // console.log("블루블랙 검색 결과 가격 : ", price);
158 192
159 - blueblack += `[${blueblack_title}](${blueblack_link}) - ${blueblack_data}` + '\n'; 193 + result += `[${title}](${link}) - ${price}` + '\n';
160 - } catch { 194 + } catch {
161 - if (i == 1) { 195 + if (i == 1) {
162 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 196 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
163 - blueblack += "검색결과 없음" + '\n'; 197 + result += "검색결과 없음" + '\n';
164 - break; 198 + break searchLoop;
165 - } else { 199 + } else {
166 - // 제품 개수가 4개 이하인 경우 200 + // 제품 개수가 4개 이하인 경우
167 - break; 201 + break searchLoop;
168 - } 202 + }
169 - } 203 + }
170 - } 204 + }
205 + break site;
206 + case 3:
207 + // 재팬나인
208 + try {
209 + await page.goto(url);
210 + // console.log("japannine crawling");
171 211
172 - // 4. 재팬나인 212 + var japannine_url = url + search + "&sort=price"
173 - try { 213 + await page.goto(japannine_url);
174 - console.log("japannine crawling"); 214 + // console.log("japannine crawling");
175 - await page .goto('http://www.japan9.co.kr');
176 215
177 - // args[0] 검색 216 + // 페이지 로딩 대기
178 - await page.waitForSelector('body > center > table:nth-child(7) > tbody > tr > td > table:nth-child(1) > tbody > tr > td:nth-child(2) > table > tbody > tr > td:nth-child(2) > input'); 217 + await page.waitForSelector('#mk_search_production > tbody > tr:nth-child(17) > td:nth-child(3) > a');
179 - await page .type('body > center > table:nth-child(7) > tbody > tr > td > table:nth-child(1) > tbody > tr > td:nth-child(2) > table > tbody > tr > td:nth-child(2) > input', args[0]); 218 + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
180 - await page .keyboard.press( "Enter" );
181 - // await page.screenshot({ path : "screenshot.png" });
182 - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지
183 219
184 - // 검색 결과 가져오기 (최대 4개) 220 + // 검색 결과 가져오기 (최대 4개)
185 - var japannine = ''; 221 + searchLoop : for (var i = 1; i <= 4; i++) {
186 - for (var i = 1; i <= 4; i++) { 222 + try {
187 - try { 223 + var title = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a', element => {
188 - var title = await page.waitForSelector('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a'); 224 + return element.textContent;
189 - var japannine_title = await page.evaluate( title => title.textContent, title ); 225 + });
190 - // console.log("재팬나인 검색 결과 제품명 : ", japannine_title); 226 + // console.log("재팬나인 검색 결과 제품명 : ", title);
191 227
192 - // 재팬나인 구조상 제품명 앞에 항상 '/n'이 붙는다 -> 제거 228 + // 재팬나인 구조상 제품명 앞에 항상 '/n'이 붙는다 -> 제거
193 - japannine_title = japannine_title.slice(1); 229 + title = title.slice(1);
194 - // 재팬나인 구조상 제품명 앞과 뒤에 [쿠폰적용 || 주문예약상품]이 붙는 경우가 많음 -> 제거 230 + // 재팬나인 구조상 제품명 앞과 뒤에 [쿠폰적용 || 주문예약상품]이 붙는 경우가 많음 -> 제거
195 - if (japannine_title.indexOf('[') == 0) { japannine_title = japannine_title.slice(japannine_title.indexOf(']')+1); } 231 + if (title.indexOf('[') == 0) { title = title.slice(title.indexOf(']')+1); }
196 - if (japannine_title.lastIndexOf(']') == japannine_title.length-1) { japannine_title = japannine_title.slice(0, japannine_title.lastIndexOf('[')); } 232 + if (title.lastIndexOf(']') == title.length-1) { title = title.slice(0, title.lastIndexOf('[')); }
197 - if (japannine_title.indexOf('{') == 0) { japannine_title = japannine_title.slice(japannine_title.indexOf('}')+1); } 233 + if (title.indexOf('{') == 0) { title = title.slice(title.indexOf('}')+1); }
198 - if (japannine_title.lastIndexOf('}') == japannine_title.length-1) { japannine_title = japannine_title.slice(0, japannine_title.lastIndexOf('{')); } 234 + if (title.lastIndexOf('}') == title.length-1) { title = title.slice(0, title.lastIndexOf('{')); }
199 235
200 - var link = await page.waitForSelector('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a'); 236 + var link = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a', element => {
201 - var japannine_link = await page.evaluate( link => link.href, link ); 237 + return element.href;
202 - // console.log("재팬나인 검색 링크 : ", japannine_link); 238 + });
203 - 239 + // console.log("재팬나인 검색 링크 : ", link);
204 - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 240 +
205 - // -> 글자수 제한(1024)도 있으므로 제거 241 + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음
206 - japannine_link = japannine_link.slice(0, japannine_link.indexOf('&search')); 242 + // -> 글자수 제한(1024)도 있으므로 제거
243 + link = link.slice(0, link.indexOf('&search'));
207 244
208 - try { 245 + try {
209 - // 품절 아이콘이 있는지 확인 246 + // 품절 아이콘이 있는지 확인
210 - var img_src = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(6) > img', element => { 247 + var img_src = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(6) > img', element => {
211 - return element.getAttribute("src"); 248 + return element.getAttribute("src");
212 - }); 249 + });
213 250
214 - if (img_src.indexOf('no_amount0') != -1) { japannine_data = 'SOLD OUT'; } 251 + if (img_src.indexOf('no_amount0') != -1) { var price = 'SOLD OUT'; }
215 - } catch { 252 + } catch {
216 - // 품절 아이콘이 없을 경우 253 + // 품절 아이콘이 없을 경우
217 - var price = await page.waitForSelector('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td.brandprice > span'); 254 + var price = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td.brandprice > span', element => {
218 - var japannine_data = await page.evaluate( price => price.textContent, price ); 255 + return element.textContent;
219 - // console.log("재팬나인 검색 결과 가격 : ", japannine_data); 256 + });
220 257
221 - // 재팬나인 구조상 금액 뒤에 (옵션에 따라 변동)이 붙는 경우가 있다 -> 제거 258 + // 재팬나인 구조상 금액 뒤에 (옵션에 따라 변동)이 붙는 경우가 있다 -> 제거
222 - if (japannine_data.indexOf('(') != -1) { japannine_data = japannine_data.slice(0, japannine_data.indexOf('원')+1); } 259 + if (price.indexOf('(') != -1) { price = price.slice(0, price.indexOf('원')+1); }
260 + }
261 + // console.log("재팬나인 검색 결과 가격 : ", price);
262 +
263 + result += `[${title}](${link}) - ${price}` + '\n';
264 + } catch {
265 + if (i == 1) {
266 + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
267 + result += "검색결과 없음" + '\n';
268 + break searchLoop;
269 + } else {
270 + // 제품 개수가 4개 이하인 경우
271 + break searchLoop;
272 + }
273 + }
274 + }
275 + break site;
223 } 276 }
224 277
225 - japannine += `[${japannine_title}](${japannine_link}) - ${japannine_data}` + '\n'; 278 + return result;
226 - } catch { 279 + });
227 - if (i == 1) { 280 + }))
228 - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시
229 - japannine += "검색결과 없음" + '\n';
230 - break;
231 - } else {
232 - // 제품 개수가 4개 이하인 경우
233 - break;
234 - }
235 - }
236 - }
237 -
238 - // 브라우저 닫기
239 - await browser.close();
240 - console.log('Browser Closed');
241 -
242 - // 검색 결과 챗봇에 출력
243 - let Commands = new Discord.MessageEmbed()
244 - .setTitle(`${args[0]}에 대한 검색 결과`)
245 - .setColor("E5D49A")
246 - // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액)
247 - .addField('베스트펜', `${bestpen.slice(0, 1023)}`)
248 - // 펜카페 검색 결과
249 - .addField('펜카페', `${pencafe.slice(0, 1023)}`)
250 - // 블루블랙 검색 결과
251 - .addField('블루블랙', `${blueblack.slice(0, 1023)}`)
252 - // 재팬나인 검색 결과
253 - .addField('재팬나인', `${japannine.slice(0, 1023)}`)
254 - msg.reply({ embeds: [Commands] });
255 }); 281 });
256 282
257 - // 검색 대기 시간이 길어질 수 있으므로 사용자에게 진행상황을 알려줄 필요가 있다 283 + // 검색 결과 챗봇에 출력
258 - msg.reply("검색중 ..."); 284 + let Commands = new Discord.MessageEmbed()
285 + .setTitle(`${search}에 대한 검색 결과`)
286 + .setColor("E5D49A")
287 + // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액)
288 + .addField('베스트펜', `${results[0].slice(0, 1023)}`)
289 + // 펜카페 검색 결과
290 + .addField('펜카페', `${results[1].slice(0, 1023)}`)
291 + // 블루블랙 검색 결과
292 + .addField('블루블랙', `${results[2].slice(0, 1023)}`)
293 + // 재팬나인 검색 결과
294 + .addField('재팬나인', `${results[3].slice(0, 1023)}`)
295 + msg.reply({ embeds: [Commands] });
259 } else { 296 } else {
260 msg.reply("검색어가 없습니다. 검색어를 추가해서 다시 입력해주세요."); 297 msg.reply("검색어가 없습니다. 검색어를 추가해서 다시 입력해주세요.");
261 } 298 }
......