Showing
1 changed file
with
88 additions
and
19 deletions
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 | - // 검색어 한 문장으로 합치기 | ||
5 | - const search = args.join(' '); | ||
6 | - // console.log(search); | ||
7 | - | ||
8 | // 각 사이트별 제품 검색 | 4 | // 각 사이트별 제품 검색 |
9 | const puppeteer = require('puppeteer'); //include Puppeteer Library | 5 | const puppeteer = require('puppeteer'); //include Puppeteer Library |
10 | puppeteer.launch({headless:true}).then(async browser => { | 6 | puppeteer.launch({headless:true}).then(async browser => { |
... | @@ -17,10 +13,10 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -17,10 +13,10 @@ exports.run = async (client, msg, args, prefix) => { |
17 | console.log("bestpen crawling"); | 13 | console.log("bestpen crawling"); |
18 | await page .goto('http://www.bestpen.kr'); | 14 | await page .goto('http://www.bestpen.kr'); |
19 | 15 | ||
20 | - // 검색창으로 이동 & search 검색 | 16 | + // 검색창으로 이동 & args[0] 검색 |
21 | await page.waitForSelector('#header > div.headerBtm > div > p.searchOpen > i'); | 17 | await page.waitForSelector('#header > div.headerBtm > div > p.searchOpen > i'); |
22 | await page .click('#header > div.headerBtm > div > p.searchOpen > i'); | 18 | await page .click('#header > div.headerBtm > div > p.searchOpen > i'); |
23 | - await page .type('#keyword', search); | 19 | + await page .type('#keyword', args[0]); |
24 | await page .keyboard.press( "Enter" ); | 20 | await page .keyboard.press( "Enter" ); |
25 | // await page.screenshot({ path : "screenshot.png" }); | 21 | // await page.screenshot({ path : "screenshot.png" }); |
26 | } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | 22 | } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 |
... | @@ -68,9 +64,9 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -68,9 +64,9 @@ exports.run = async (client, msg, args, prefix) => { |
68 | console.log("pencafe crawling"); | 64 | console.log("pencafe crawling"); |
69 | await page .goto('http://www.pencafe.co.kr'); | 65 | await page .goto('http://www.pencafe.co.kr'); |
70 | 66 | ||
71 | - // search 검색 | 67 | + // args[0] 검색 |
72 | await page.waitForSelector('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input'); | 68 | await page.waitForSelector('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input'); |
73 | - await page .type('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input', search); | 69 | + await page .type('#header > div.hd_mib > div.hd_sch.f_left > form > fieldset > input', args[0]); |
74 | await page .keyboard.press( "Enter" ); | 70 | await page .keyboard.press( "Enter" ); |
75 | // await page.screenshot({ path : "screenshot.png" }); | 71 | // await page.screenshot({ path : "screenshot.png" }); |
76 | } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | 72 | } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 |
... | @@ -86,7 +82,7 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -86,7 +82,7 @@ exports.run = async (client, msg, args, prefix) => { |
86 | // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거 | 82 | // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거 |
87 | if (pencafe_title.indexOf('%') != -1) { pencafe_title = pencafe_title.slice(pencafe_title.indexOf('%')+1); } | 83 | if (pencafe_title.indexOf('%') != -1) { pencafe_title = pencafe_title.slice(pencafe_title.indexOf('%')+1); } |
88 | // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거 | 84 | // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거 |
89 | - if (pencafe_title.indexOf('(') != -1) { pencafe_title = pencafe_title.slice(0, pencafe_title.lastIndexOf('(')); } | 85 | + if (pencafe_title.lastIndexOf(')') == pencafe_title.length-1) { pencafe_title = pencafe_title.slice(0, pencafe_title.lastIndexOf('(')); } |
90 | 86 | ||
91 | var link = await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dd > ul > li.prd-name > a'); | 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'); |
92 | var pencafe_link = await page.evaluate( link => link.href, link ); | 88 | var pencafe_link = await page.evaluate( link => link.href, link ); |
... | @@ -109,7 +105,7 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -109,7 +105,7 @@ exports.run = async (client, msg, args, prefix) => { |
109 | } catch { | 105 | } catch { |
110 | if (i == 1) { | 106 | if (i == 1) { |
111 | // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | 107 | // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 |
112 | - pencafe += "검색결과 없음" + '\n' | 108 | + pencafe += "검색결과 없음" + '\n'; |
113 | break; | 109 | break; |
114 | } else { | 110 | } else { |
115 | // 제품 개수가 4개 이하인 경우 | 111 | // 제품 개수가 4개 이하인 경우 |
... | @@ -123,9 +119,9 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -123,9 +119,9 @@ exports.run = async (client, msg, args, prefix) => { |
123 | console.log("blueblack crawling"); | 119 | console.log("blueblack crawling"); |
124 | await page .goto('https://blueblack.co.kr'); | 120 | await page .goto('https://blueblack.co.kr'); |
125 | 121 | ||
126 | - // search 검색 | 122 | + // args[0] 검색 |
127 | await page.waitForSelector('#keyword'); | 123 | await page.waitForSelector('#keyword'); |
128 | - await page .type('#keyword', search); | 124 | + await page .type('#keyword', args[0]); |
129 | await page .keyboard.press( "Enter" ); | 125 | await page .keyboard.press( "Enter" ); |
130 | // await page.screenshot({ path : "screenshot.png" }); | 126 | // await page.screenshot({ path : "screenshot.png" }); |
131 | } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | 127 | } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 |
... | @@ -142,9 +138,9 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -142,9 +138,9 @@ exports.run = async (client, msg, args, prefix) => { |
142 | var blueblack_link = await page.evaluate( link => link.href, link ); | 138 | var blueblack_link = await page.evaluate( link => link.href, link ); |
143 | // console.log("블루블랙 검색 링크 : ", blueblack_link); | 139 | // console.log("블루블랙 검색 링크 : ", blueblack_link); |
144 | 140 | ||
145 | - 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)'); | 141 | + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 |
146 | - var blueblack_data = await page.evaluate( price => price.textContent, price ); | 142 | + // -> 글자수 제한(1024)도 있으므로 제거 |
147 | - // console.log("블루블랙 검색 결과 가격 : ", blueblack_data); | 143 | + pencafe_link = pencafe_link.slice(0, pencafe_link.indexOf('&cate_no')); |
148 | 144 | ||
149 | try { | 145 | try { |
150 | // 품절 아이콘이 있는지 확인 | 146 | // 품절 아이콘이 있는지 확인 |
... | @@ -152,14 +148,85 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -152,14 +148,85 @@ exports.run = async (client, msg, args, prefix) => { |
152 | return element.getAttribute("src"); | 148 | return element.getAttribute("src"); |
153 | }); | 149 | }); |
154 | 150 | ||
155 | - blueblack_data = 'SOLD OUT' | 151 | + blueblack_data = 'SOLD OUT'; |
156 | - } catch { ; } | 152 | + } catch { |
153 | + // 품절 아이콘이 없을 경우 | ||
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)'); | ||
155 | + var blueblack_data = await page.evaluate( price => price.textContent, price ); | ||
156 | + // console.log("블루블랙 검색 결과 가격 : ", blueblack_data); | ||
157 | + } | ||
157 | 158 | ||
158 | blueblack += `[${blueblack_title}](${blueblack_link}) - ${blueblack_data}` + '\n'; | 159 | blueblack += `[${blueblack_title}](${blueblack_link}) - ${blueblack_data}` + '\n'; |
159 | } catch { | 160 | } catch { |
160 | if (i == 1) { | 161 | if (i == 1) { |
161 | // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | 162 | // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 |
162 | - blueblack += "검색결과 없음" + '\n' | 163 | + blueblack += "검색결과 없음" + '\n'; |
164 | + break; | ||
165 | + } else { | ||
166 | + // 제품 개수가 4개 이하인 경우 | ||
167 | + break; | ||
168 | + } | ||
169 | + } | ||
170 | + } | ||
171 | + | ||
172 | + // 4. 재팬나인 | ||
173 | + try { | ||
174 | + console.log("japannine crawling"); | ||
175 | + await page .goto('http://www.japan9.co.kr'); | ||
176 | + | ||
177 | + // args[0] 검색 | ||
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'); | ||
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]); | ||
180 | + await page .keyboard.press( "Enter" ); | ||
181 | + // await page.screenshot({ path : "screenshot.png" }); | ||
182 | + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | ||
183 | + | ||
184 | + // 검색 결과 가져오기 (최대 4개) | ||
185 | + var japannine = ''; | ||
186 | + for (var i = 1; i <= 4; i++) { | ||
187 | + try { | ||
188 | + var title = await page.waitForSelector('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a'); | ||
189 | + var japannine_title = await page.evaluate( title => title.textContent, title ); | ||
190 | + // console.log("재팬나인 검색 결과 제품명 : ", japannine_title); | ||
191 | + | ||
192 | + // 재팬나인 구조상 제품명 앞에 항상 '/n'이 붙는다 -> 제거 | ||
193 | + japannine_title = japannine_title.slice(1); | ||
194 | + // 재팬나인 구조상 제품명 앞과 뒤에 [쿠폰적용 || 주문예약상품]이 붙는 경우가 많음 -> 제거 | ||
195 | + if (japannine_title.indexOf('[') == 0) { japannine_title = japannine_title.slice(japannine_title.indexOf(']')+1); } | ||
196 | + if (japannine_title.lastIndexOf(']') == japannine_title.length-1) { japannine_title = japannine_title.slice(0, japannine_title.lastIndexOf('[')); } | ||
197 | + if (japannine_title.indexOf('{') == 0) { japannine_title = japannine_title.slice(japannine_title.indexOf('}')+1); } | ||
198 | + if (japannine_title.lastIndexOf('}') == japannine_title.length-1) { japannine_title = japannine_title.slice(0, japannine_title.lastIndexOf('{')); } | ||
199 | + | ||
200 | + var link = await page.waitForSelector('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a'); | ||
201 | + var japannine_link = await page.evaluate( link => link.href, link ); | ||
202 | + // console.log("재팬나인 검색 링크 : ", japannine_link); | ||
203 | + | ||
204 | + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
205 | + // -> 글자수 제한(1024)도 있으므로 제거 | ||
206 | + japannine_link = japannine_link.slice(0, japannine_link.indexOf('&search')); | ||
207 | + | ||
208 | + try { | ||
209 | + // 품절 아이콘이 있는지 확인 | ||
210 | + 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"); | ||
212 | + }); | ||
213 | + | ||
214 | + if (img_src.indexOf('no_amount0') != -1) { japannine_data = 'SOLD OUT'; } | ||
215 | + } catch { | ||
216 | + // 품절 아이콘이 없을 경우 | ||
217 | + var price = await page.waitForSelector('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td.brandprice > span'); | ||
218 | + var japannine_data = await page.evaluate( price => price.textContent, price ); | ||
219 | + // console.log("재팬나인 검색 결과 가격 : ", japannine_data); | ||
220 | + | ||
221 | + // 재팬나인 구조상 금액 뒤에 (옵션에 따라 변동)이 붙는 경우가 있다 -> 제거 | ||
222 | + if (japannine_data.indexOf('(') != -1) { japannine_data = japannine_data.slice(0, japannine_data.indexOf('원')+1); } | ||
223 | + } | ||
224 | + | ||
225 | + japannine += `[${japannine_title}](${japannine_link}) - ${japannine_data}` + '\n'; | ||
226 | + } catch { | ||
227 | + if (i == 1) { | ||
228 | + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | ||
229 | + japannine += "검색결과 없음" + '\n'; | ||
163 | break; | 230 | break; |
164 | } else { | 231 | } else { |
165 | // 제품 개수가 4개 이하인 경우 | 232 | // 제품 개수가 4개 이하인 경우 |
... | @@ -174,7 +241,7 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -174,7 +241,7 @@ exports.run = async (client, msg, args, prefix) => { |
174 | 241 | ||
175 | // 검색 결과 챗봇에 출력 | 242 | // 검색 결과 챗봇에 출력 |
176 | let Commands = new Discord.MessageEmbed() | 243 | let Commands = new Discord.MessageEmbed() |
177 | - .setTitle(`${search}에 대한 검색 결과`) | 244 | + .setTitle(`${args[0]}에 대한 검색 결과`) |
178 | .setColor("E5D49A") | 245 | .setColor("E5D49A") |
179 | // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액) | 246 | // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액) |
180 | .addField('베스트펜', `${bestpen.slice(0, 1023)}`) | 247 | .addField('베스트펜', `${bestpen.slice(0, 1023)}`) |
... | @@ -182,6 +249,8 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -182,6 +249,8 @@ exports.run = async (client, msg, args, prefix) => { |
182 | .addField('펜카페', `${pencafe.slice(0, 1023)}`) | 249 | .addField('펜카페', `${pencafe.slice(0, 1023)}`) |
183 | // 블루블랙 검색 결과 | 250 | // 블루블랙 검색 결과 |
184 | .addField('블루블랙', `${blueblack.slice(0, 1023)}`) | 251 | .addField('블루블랙', `${blueblack.slice(0, 1023)}`) |
252 | + // 재팬나인 검색 결과 | ||
253 | + .addField('재팬나인', `${japannine.slice(0, 1023)}`) | ||
185 | msg.reply({ embeds: [Commands] }); | 254 | msg.reply({ embeds: [Commands] }); |
186 | }); | 255 | }); |
187 | 256 | ... | ... |
-
Please register or login to post a comment