Showing
1 changed file
with
260 additions
and
223 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 | - // 각 사이트별 제품 검색 | 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 | } | ... | ... |
-
Please register or login to post a comment