Merge branch 'ocr' into 'master'
Ocr Change the category of help function from example to help See merge request !3
Showing
4 changed files
with
228 additions
and
228 deletions
... | @@ -69,7 +69,7 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -69,7 +69,7 @@ exports.run = async (client, msg, args, prefix) => { |
69 | exports.config = { | 69 | exports.config = { |
70 | name: '도움말', | 70 | name: '도움말', |
71 | aliases: ['도움', '명령어', 'commands', 'help'], | 71 | aliases: ['도움', '명령어', 'commands', 'help'], |
72 | - category: ['example'], | 72 | + category: ['Help'], |
73 | des: ['봇에 대한 명령어 리스트들을 불러옵니다.'], | 73 | des: ['봇에 대한 명령어 리스트들을 불러옵니다.'], |
74 | use: ['!도움말 <명령어>'] | 74 | use: ['!도움말 <명령어>'] |
75 | }; | 75 | }; |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -75,14 +75,11 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -75,14 +75,11 @@ exports.run = async (client, msg, args, prefix) => { |
75 | } | 75 | } |
76 | }; | 76 | }; |
77 | 77 | ||
78 | -function kor(attachment) { | ||
79 | - | ||
80 | -} | ||
81 | 78 | ||
82 | exports.config = { | 79 | exports.config = { |
83 | name: 'ocr', | 80 | name: 'ocr', |
84 | aliases: ['ㅐㅊㄱ'], | 81 | aliases: ['ㅐㅊㄱ'], |
85 | - category: ['ocr'], | 82 | + category: ['Ocr'], |
86 | des: ['이미지를 첨부하고 명령어를 입력하면, 이미지에 있는 텍스트를 추출합니다.'], | 83 | des: ['이미지를 첨부하고 명령어를 입력하면, 이미지에 있는 텍스트를 추출합니다.'], |
87 | use: ['!ocr <사용 언어>'] | 84 | use: ['!ocr <사용 언어>'] |
88 | }; | 85 | }; |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -7,19 +7,19 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -7,19 +7,19 @@ exports.run = async (client, msg, args, prefix) => { |
7 | 7 | ||
8 | // 검색 대기 시간이 길어질 수 있으므로 사용자에게 진행상황을 알려줄 필요가 있다 | 8 | // 검색 대기 시간이 길어질 수 있으므로 사용자에게 진행상황을 알려줄 필요가 있다 |
9 | msg.reply("검색중 ..."); | 9 | msg.reply("검색중 ..."); |
10 | - | 10 | + |
11 | //include Puppeteer Library | 11 | //include Puppeteer Library |
12 | const puppeteer = require('puppeteer'); | 12 | const puppeteer = require('puppeteer'); |
13 | 13 | ||
14 | const withBrowser = async (fn) => { | 14 | const withBrowser = async (fn) => { |
15 | - const browser = await puppeteer.launch({headless:true}); | 15 | + const browser = await puppeteer.launch({ headless: true }); |
16 | try { | 16 | try { |
17 | return await fn(browser); | 17 | return await fn(browser); |
18 | } finally { | 18 | } finally { |
19 | await browser.close(); | 19 | await browser.close(); |
20 | } | 20 | } |
21 | - } | 21 | + }; |
22 | - | 22 | + |
23 | const withPage = (browser) => async (fn) => { | 23 | const withPage = (browser) => async (fn) => { |
24 | const page = await browser.newPage(); | 24 | const page = await browser.newPage(); |
25 | try { | 25 | try { |
... | @@ -27,7 +27,7 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -27,7 +27,7 @@ exports.run = async (client, msg, args, prefix) => { |
27 | } finally { | 27 | } finally { |
28 | await page.close(); | 28 | await page.close(); |
29 | } | 29 | } |
30 | - } | 30 | + }; |
31 | 31 | ||
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=']; | 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=']; |
33 | const results = await withBrowser(async (browser) => { | 33 | const results = await withBrowser(async (browser) => { |
... | @@ -35,263 +35,265 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -35,263 +35,265 @@ exports.run = async (client, msg, args, prefix) => { |
35 | return withPage(browser)(async (page) => { | 35 | return withPage(browser)(async (page) => { |
36 | // 각 사이트별 제품 검색 | 36 | // 각 사이트별 제품 검색 |
37 | var result = ''; | 37 | var result = ''; |
38 | - site : switch(urls.indexOf(url)) { | 38 | + site: switch (urls.indexOf(url)) { |
39 | - case 0: | 39 | + case 0: |
40 | - // 베스트펜 | 40 | + // 베스트펜 |
41 | - try { | ||
42 | - var bestpen_url = url + search + "&sort=price" | ||
43 | - await page.goto(bestpen_url); | ||
44 | - // console.log("bestpen crawling"); | ||
45 | - | ||
46 | - // 페이지 로딩 대기 | ||
47 | - await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a'); | ||
48 | - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | ||
49 | - | ||
50 | - // 검색 결과 가져오기 (최대 4개) | ||
51 | - searchLoop : for (var i = 1; i <= 4; i++) { | ||
52 | try { | 41 | 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 => { | 42 | + var bestpen_url = url + search + "&sort=price"; |
54 | - return element.textContent; | 43 | + await page.goto(bestpen_url); |
55 | - }); | 44 | + // console.log("bestpen crawling"); |
56 | - // console.log("베스트펜 검색 결과 제품명 : ", title); | 45 | + |
57 | - | 46 | + // 페이지 로딩 대기 |
58 | - var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child('+i+') > dt > a', element => { | 47 | + await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a'); |
59 | - return element.href; | 48 | + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 |
60 | - }); | 49 | + |
61 | - // console.log("베스트펜 검색 링크 : ", link); | 50 | + // 검색 결과 가져오기 (최대 4개) |
62 | - | 51 | + searchLoop: for (var i = 1; i <= 4; i++) { |
63 | - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
64 | - // -> 글자수 제한(1024)도 있으므로 제거 | ||
65 | - link = link.slice(0, link.indexOf('&search')); | ||
66 | - | ||
67 | try { | 52 | 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 => { | 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 => { |
69 | return element.textContent; | 54 | return element.textContent; |
70 | }); | 55 | }); |
71 | - // console.log("베스트펜 검색 결과 가격 : ", price); | 56 | + // console.log("베스트펜 검색 결과 제품명 : ", title); |
72 | - } catch { | 57 | + |
73 | - // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시 | 58 | + var link = await page.$eval('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(' + i + ') > dt > a', element => { |
74 | - price = "SOLD OUT"; | 59 | + return element.href; |
75 | - } | 60 | + }); |
61 | + // console.log("베스트펜 검색 링크 : ", link); | ||
62 | + | ||
63 | + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
64 | + // -> 글자수 제한(1024)도 있으므로 제거 | ||
65 | + link = link.slice(0, link.indexOf('&search')); | ||
76 | 66 | ||
77 | - result += `[${title}](${link}) - ${price}` + '\n'; | 67 | + try { |
78 | - } catch { | 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 => { |
79 | - if (i == 1) { | 69 | + return element.textContent; |
80 | - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | 70 | + }); |
81 | - result += "검색결과 없음" + '\n'; | 71 | + // console.log("베스트펜 검색 결과 가격 : ", price); |
82 | - break searchLoop; | 72 | + } catch { |
83 | - } else { | 73 | + // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시 |
84 | - // 제품 개수가 4개 이하인 경우 | 74 | + price = "SOLD OUT"; |
85 | - break searchLoop; | 75 | + } |
76 | + | ||
77 | + result += `[${title}](${link}) - ${price}` + '\n'; | ||
78 | + } catch { | ||
79 | + if (i == 1) { | ||
80 | + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | ||
81 | + result += "검색결과 없음" + '\n'; | ||
82 | + break searchLoop; | ||
83 | + } else { | ||
84 | + // 제품 개수가 4개 이하인 경우 | ||
85 | + break searchLoop; | ||
86 | + } | ||
86 | } | 87 | } |
87 | } | 88 | } |
88 | - } | 89 | + break site; |
89 | - break site; | 90 | + case 1: |
90 | - case 1: | 91 | + // 펜카페 |
91 | - // 펜카페 | ||
92 | - try { | ||
93 | - var pencafe_url = url + search + "&sort=price" | ||
94 | - await page.goto(pencafe_url); | ||
95 | - // console.log("pencafe crawling"); | ||
96 | - | ||
97 | - // 페이지 로딩 대기 | ||
98 | - await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a'); | ||
99 | - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | ||
100 | - | ||
101 | - // 검색 결과 가져오기 (최대 4개) | ||
102 | - searchLoop : for (var i = 1; i <= 4; i++) { | ||
103 | try { | 92 | try { |
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 => { | 93 | + var pencafe_url = url + search + "&sort=price"; |
105 | - return element.textContent; | 94 | + await page.goto(pencafe_url); |
106 | - }); | 95 | + // console.log("pencafe crawling"); |
107 | - // console.log("펜카페 검색 결과 제품명 : ", title); | 96 | + |
108 | - | 97 | + // 페이지 로딩 대기 |
109 | - // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거 | 98 | + await page.waitForSelector('#searchWrap > div > div.item-wrap > div:nth-child(2) > dl:nth-child(4) > dd > ul > li.prd-name > a'); |
110 | - if (title.indexOf('%') != -1) { title = title.slice(title.indexOf('%')+1); } | 99 | + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 |
111 | - // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거 | 100 | + |
112 | - if (title.lastIndexOf(')') == title.length-1) { title = title.slice(0, title.lastIndexOf('(')); } | 101 | + // 검색 결과 가져오기 (최대 4개) |
113 | - | 102 | + searchLoop: for (var i = 1; i <= 4; i++) { |
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 => { | ||
115 | - return element.href; | ||
116 | - }); | ||
117 | - // console.log("펜카페 검색 링크 : ", link); | ||
118 | - | ||
119 | - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
120 | - // -> 글자수 제한(1024)도 있으므로 제거 | ||
121 | - link = link.slice(0, link.indexOf('&search')); | ||
122 | - | ||
123 | try { | 103 | try { |
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 => { | 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 => { |
125 | return element.textContent; | 105 | return element.textContent; |
126 | }); | 106 | }); |
127 | - // console.log("펜카페 검색 결과 가격 : ", price); | 107 | + // console.log("펜카페 검색 결과 제품명 : ", title); |
128 | - } catch { | ||
129 | - // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시 | ||
130 | - price = "SOLD OUT"; | ||
131 | - } | ||
132 | 108 | ||
133 | - result += `[${title}](${link}) - ${price}` + '\n'; | 109 | + // 펜카페 구조상 제품명 앞에 할인률(ex. 17%)이 붙는 경우가 많음 -> 제거 |
134 | - } catch { | 110 | + if (title.indexOf('%') != -1) { title = title.slice(title.indexOf('%') + 1); } |
135 | - if (i == 1) { | 111 | + // 펜카페 구조상 제품명 뒤에 사족(ex. (색상선택/금장~~~))이 붙는 경우가 많음 -> 제거 |
136 | - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | 112 | + if (title.lastIndexOf(')') == title.length - 1) { title = title.slice(0, title.lastIndexOf('(')); } |
137 | - result += "검색결과 없음" + '\n'; | 113 | + |
138 | - break searchLoop; | 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 => { |
139 | - } else { | 115 | + return element.href; |
140 | - // 제품 개수가 4개 이하인 경우 | 116 | + }); |
141 | - break searchLoop; | 117 | + // console.log("펜카페 검색 링크 : ", link); |
118 | + | ||
119 | + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
120 | + // -> 글자수 제한(1024)도 있으므로 제거 | ||
121 | + link = link.slice(0, link.indexOf('&search')); | ||
122 | + | ||
123 | + try { | ||
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 => { | ||
125 | + return element.textContent; | ||
126 | + }); | ||
127 | + // console.log("펜카페 검색 결과 가격 : ", price); | ||
128 | + } catch { | ||
129 | + // 품절이라서 금액정보가 없을 경우 "SOLD OUT"으로 표시 | ||
130 | + price = "SOLD OUT"; | ||
131 | + } | ||
132 | + | ||
133 | + result += `[${title}](${link}) - ${price}` + '\n'; | ||
134 | + } catch { | ||
135 | + if (i == 1) { | ||
136 | + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | ||
137 | + result += "검색결과 없음" + '\n'; | ||
138 | + break searchLoop; | ||
139 | + } else { | ||
140 | + // 제품 개수가 4개 이하인 경우 | ||
141 | + break searchLoop; | ||
142 | + } | ||
142 | } | 143 | } |
143 | } | 144 | } |
144 | - } | 145 | + break site; |
145 | - break site; | 146 | + case 2: |
146 | - case 2: | 147 | + // 블루블랙 |
147 | - // 블루블랙 | ||
148 | - try { | ||
149 | - var blueblack_url = url + search + "&order_by=priceasc" | ||
150 | - await page.goto(blueblack_url); | ||
151 | - // console.log("blublack crawling"); | ||
152 | - | ||
153 | - // 페이지 로딩 대기 | ||
154 | - await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child(4) > div.description > p.name > a > span:nth-child(2)'); | ||
155 | - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | ||
156 | - | ||
157 | - // 검색 결과 가져오기 (최대 4개) | ||
158 | - searchLoop : for (var i = 1; i <= 4; i++) { | ||
159 | try { | 148 | 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 => { | 149 | + var blueblack_url = url + search + "&order_by=priceasc"; |
161 | - return element.textContent; | 150 | + await page.goto(blueblack_url); |
162 | - }); | 151 | + // console.log("blublack crawling"); |
163 | - // console.log("블루블랙 검색 결과 제품명 : ", title); | ||
164 | - | ||
165 | - var link = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > p.name > a', element => { | ||
166 | - return element.href; | ||
167 | - }); | ||
168 | - // console.log("블루블랙 검색 링크 : ", link); | ||
169 | - | ||
170 | - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
171 | - // -> 글자수 제한(1024)도 있으므로 제거 | ||
172 | - link = link.slice(0, link.indexOf('&cate_no')); | ||
173 | 152 | ||
153 | + // 페이지 로딩 대기 | ||
154 | + await page.waitForSelector('#contents > div:nth-child(4) > ul > li:nth-child(4) > div.description > p.name > a > span:nth-child(2)'); | ||
155 | + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | ||
156 | + | ||
157 | + // 검색 결과 가져오기 (최대 4개) | ||
158 | + searchLoop: for (var i = 1; i <= 4; i++) { | ||
174 | try { | 159 | try { |
175 | - // 품절 아이콘이 있는지 확인 | 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 => { |
176 | - await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child('+i+') > div.description > div.status > div > img', element => { | 161 | + return element.textContent; |
177 | - return element.getAttribute("src"); | ||
178 | }); | 162 | }); |
163 | + // console.log("블루블랙 검색 결과 제품명 : ", title); | ||
164 | + | ||
165 | + var link = await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child(' + i + ') > div.description > p.name > a', element => { | ||
166 | + return element.href; | ||
167 | + }); | ||
168 | + // console.log("블루블랙 검색 링크 : ", link); | ||
169 | + | ||
170 | + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
171 | + // -> 글자수 제한(1024)도 있으므로 제거 | ||
172 | + link = link.slice(0, link.indexOf('&cate_no')); | ||
179 | 173 | ||
180 | - var price = 'SOLD OUT'; | ||
181 | - } catch { | ||
182 | try { | 174 | try { |
183 | - // 품절 아이콘이 없을 경우 | 175 | + // 품절 아이콘이 있는지 확인 |
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 => { | 176 | + await page.$eval('#contents > div:nth-child(4) > ul > li:nth-child(' + i + ') > div.description > div.status > div > img', element => { |
185 | - return element.textContent; | 177 | + return element.getAttribute("src"); |
186 | }); | 178 | }); |
179 | + | ||
180 | + var price = 'SOLD OUT'; | ||
187 | } catch { | 181 | } catch { |
188 | - var price = '0원'; | 182 | + try { |
183 | + // 품절 아이콘이 없을 경우 | ||
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 => { | ||
185 | + return element.textContent; | ||
186 | + }); | ||
187 | + } catch { | ||
188 | + var price = '0원'; | ||
189 | + } | ||
190 | + } | ||
191 | + // console.log("블루블랙 검색 결과 가격 : ", price); | ||
192 | + | ||
193 | + result += `[${title}](${link}) - ${price}` + '\n'; | ||
194 | + } catch { | ||
195 | + if (i == 1) { | ||
196 | + // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | ||
197 | + result += "검색결과 없음" + '\n'; | ||
198 | + break searchLoop; | ||
199 | + } else { | ||
200 | + // 제품 개수가 4개 이하인 경우 | ||
201 | + break searchLoop; | ||
189 | } | 202 | } |
190 | - } | ||
191 | - // console.log("블루블랙 검색 결과 가격 : ", price); | ||
192 | - | ||
193 | - result += `[${title}](${link}) - ${price}` + '\n'; | ||
194 | - } catch { | ||
195 | - if (i == 1) { | ||
196 | - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | ||
197 | - result += "검색결과 없음" + '\n'; | ||
198 | - break searchLoop; | ||
199 | - } else { | ||
200 | - // 제품 개수가 4개 이하인 경우 | ||
201 | - break searchLoop; | ||
202 | } | 203 | } |
203 | } | 204 | } |
204 | - } | 205 | + break site; |
205 | - break site; | 206 | + case 3: |
206 | - case 3: | 207 | + // 재팬나인 |
207 | - // 재팬나인 | ||
208 | - try { | ||
209 | - await page.goto(url); | ||
210 | - // console.log("japannine crawling"); | ||
211 | - | ||
212 | - var japannine_url = url + search + "&sort=price" | ||
213 | - await page.goto(japannine_url); | ||
214 | - // console.log("japannine crawling"); | ||
215 | - | ||
216 | - // 페이지 로딩 대기 | ||
217 | - await page.waitForSelector('#mk_search_production > tbody > tr:nth-child(17) > td:nth-child(3) > a'); | ||
218 | - } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | ||
219 | - | ||
220 | - // 검색 결과 가져오기 (최대 4개) | ||
221 | - searchLoop : for (var i = 1; i <= 4; i++) { | ||
222 | try { | 208 | try { |
223 | - var title = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a', element => { | 209 | + await page.goto(url); |
224 | - return element.textContent; | 210 | + // console.log("japannine crawling"); |
225 | - }); | 211 | + |
226 | - // console.log("재팬나인 검색 결과 제품명 : ", title); | 212 | + var japannine_url = url + search + "&sort=price"; |
227 | - | 213 | + await page.goto(japannine_url); |
228 | - // 재팬나인 구조상 제품명 앞에 항상 '/n'이 붙는다 -> 제거 | 214 | + // console.log("japannine crawling"); |
229 | - title = title.slice(1); | ||
230 | - // 재팬나인 구조상 제품명 앞과 뒤에 [쿠폰적용 || 주문예약상품]이 붙는 경우가 많음 -> 제거 | ||
231 | - if (title.indexOf('[') == 0) { title = title.slice(title.indexOf(']')+1); } | ||
232 | - if (title.lastIndexOf(']') == title.length-1) { title = title.slice(0, title.lastIndexOf('[')); } | ||
233 | - if (title.indexOf('{') == 0) { title = title.slice(title.indexOf('}')+1); } | ||
234 | - if (title.lastIndexOf('}') == title.length-1) { title = title.slice(0, title.lastIndexOf('{')); } | ||
235 | - | ||
236 | - var link = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td:nth-child(3) > a', element => { | ||
237 | - return element.href; | ||
238 | - }); | ||
239 | - // console.log("재팬나인 검색 링크 : ", link); | ||
240 | - | ||
241 | - // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 | ||
242 | - // -> 글자수 제한(1024)도 있으므로 제거 | ||
243 | - link = link.slice(0, link.indexOf('&search')); | ||
244 | 215 | ||
216 | + // 페이지 로딩 대기 | ||
217 | + await page.waitForSelector('#mk_search_production > tbody > tr:nth-child(17) > td:nth-child(3) > a'); | ||
218 | + } catch { ; } // 사이트 링크에 이상이 생겼거나 검색에 문제가 생겼을 경우 프로그램이 종료되는 것을 방지 | ||
219 | + | ||
220 | + // 검색 결과 가져오기 (최대 4개) | ||
221 | + searchLoop: for (var i = 1; i <= 4; i++) { | ||
245 | try { | 222 | try { |
246 | - // 품절 아이콘이 있는지 확인 | 223 | + var title = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td:nth-child(3) > a', 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 => { | 224 | + return element.textContent; |
248 | - return element.getAttribute("src"); | ||
249 | }); | 225 | }); |
226 | + // console.log("재팬나인 검색 결과 제품명 : ", title); | ||
250 | 227 | ||
251 | - if (img_src.indexOf('no_amount0') != -1) { var price = 'SOLD OUT'; } | 228 | + // 재팬나인 구조상 제품명 앞에 항상 '/n'이 붙는다 -> 제거 |
252 | - } catch { | 229 | + title = title.slice(1); |
253 | - // 품절 아이콘이 없을 경우 | 230 | + // 재팬나인 구조상 제품명 앞과 뒤에 [쿠폰적용 || 주문예약상품]이 붙는 경우가 많음 -> 제거 |
254 | - var price = await page.$eval('#mk_search_production > tbody > tr:nth-child('+(5+((i-1)*4))+') > td.brandprice > span', element => { | 231 | + if (title.indexOf('[') == 0) { title = title.slice(title.indexOf(']') + 1); } |
255 | - return element.textContent; | 232 | + if (title.lastIndexOf(']') == title.length - 1) { title = title.slice(0, title.lastIndexOf('[')); } |
233 | + if (title.indexOf('{') == 0) { title = title.slice(title.indexOf('}') + 1); } | ||
234 | + if (title.lastIndexOf('}') == title.length - 1) { title = title.slice(0, title.lastIndexOf('{')); } | ||
235 | + | ||
236 | + var link = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td:nth-child(3) > a', element => { | ||
237 | + return element.href; | ||
256 | }); | 238 | }); |
239 | + // console.log("재팬나인 검색 링크 : ", link); | ||
257 | 240 | ||
258 | - // 재팬나인 구조상 금액 뒤에 (옵션에 따라 변동)이 붙는 경우가 있다 -> 제거 | 241 | + // 링크 구조상 &search 뒷부분은 제품 링크를 띄우는데 영향을 미치지 않음 |
259 | - if (price.indexOf('(') != -1) { price = price.slice(0, price.indexOf('원')+1); } | 242 | + // -> 글자수 제한(1024)도 있으므로 제거 |
260 | - } | 243 | + link = link.slice(0, link.indexOf('&search')); |
261 | - // console.log("재팬나인 검색 결과 가격 : ", price); | 244 | + |
262 | - | 245 | + try { |
263 | - result += `[${title}](${link}) - ${price}` + '\n'; | 246 | + // 품절 아이콘이 있는지 확인 |
264 | - } catch { | 247 | + var img_src = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td:nth-child(6) > img', element => { |
265 | - if (i == 1) { | 248 | + return element.getAttribute("src"); |
266 | - // 제품 정보가 아예 없을 경우 "검색결과 없음"으로 표시 | 249 | + }); |
267 | - result += "검색결과 없음" + '\n'; | 250 | + |
268 | - break searchLoop; | 251 | + if (img_src.indexOf('no_amount0') != -1) { var price = 'SOLD OUT'; } |
269 | - } else { | 252 | + } catch { |
270 | - // 제품 개수가 4개 이하인 경우 | 253 | + // 품절 아이콘이 없을 경우 |
271 | - break searchLoop; | 254 | + var price = await page.$eval('#mk_search_production > tbody > tr:nth-child(' + (5 + ((i - 1) * 4)) + ') > td.brandprice > span', element => { |
255 | + return element.textContent; | ||
256 | + }); | ||
257 | + | ||
258 | + // 재팬나인 구조상 금액 뒤에 (옵션에 따라 변동)이 붙는 경우가 있다 -> 제거 | ||
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 | + } | ||
272 | } | 273 | } |
273 | } | 274 | } |
274 | - } | 275 | + break site; |
275 | - break site; | ||
276 | } | 276 | } |
277 | - | 277 | + |
278 | return result; | 278 | return result; |
279 | }); | 279 | }); |
280 | - })) | 280 | + })); |
281 | }); | 281 | }); |
282 | 282 | ||
283 | // 검색 결과 챗봇에 출력 | 283 | // 검색 결과 챗봇에 출력 |
284 | let Commands = new Discord.MessageEmbed() | 284 | let Commands = new Discord.MessageEmbed() |
285 | - .setTitle(`${search}에 대한 검색 결과`) | 285 | + |
286 | - .setColor("E5D49A") | 286 | + .setTitle(`${search}에 대한 검색 결과`) |
287 | - // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액) | 287 | + .setColor("E5D49A") |
288 | - .addField('베스트펜', `${results[0].slice(0, 1023)}`) | 288 | + // 베스트펜 검색 결과 (ex. 제품명(링크) - 금액) |
289 | - // 펜카페 검색 결과 | 289 | + .addField('베스트펜', `${results[0].slice(0, 1023)}`) |
290 | - .addField('펜카페', `${results[1].slice(0, 1023)}`) | 290 | + // 펜카페 검색 결과 |
291 | - // 블루블랙 검색 결과 | 291 | + .addField('펜카페', `${results[1].slice(0, 1023)}`) |
292 | - .addField('블루블랙', `${results[2].slice(0, 1023)}`) | 292 | + // 블루블랙 검색 결과 |
293 | - // 재팬나인 검색 결과 | 293 | + .addField('블루블랙', `${results[2].slice(0, 1023)}`) |
294 | - .addField('재팬나인', `${results[3].slice(0, 1023)}`) | 294 | + // 재팬나인 검색 결과 |
295 | + .addField('재팬나인', `${results[3].slice(0, 1023)}`); | ||
296 | + | ||
295 | msg.reply({ embeds: [Commands] }); | 297 | msg.reply({ embeds: [Commands] }); |
296 | } else { | 298 | } else { |
297 | msg.reply("검색어가 없습니다. 검색어를 추가해서 다시 입력해주세요."); | 299 | msg.reply("검색어가 없습니다. 검색어를 추가해서 다시 입력해주세요."); |
... | @@ -300,8 +302,9 @@ exports.run = async (client, msg, args, prefix) => { | ... | @@ -300,8 +302,9 @@ exports.run = async (client, msg, args, prefix) => { |
300 | 302 | ||
301 | exports.config = { | 303 | exports.config = { |
302 | name: '문구', | 304 | name: '문구', |
305 | + | ||
303 | aliases: ['문구류', '가격비교', 'stationery', 'search'], | 306 | aliases: ['문구류', '가격비교', 'stationery', 'search'], |
304 | - category: ['stationery'], | 307 | + category: ['Stationery'], |
305 | des: ['채팅 내용에 대한 검색결과를 보여줍니다.'], | 308 | des: ['채팅 내용에 대한 검색결과를 보여줍니다.'], |
306 | use: ['!문구 <채팅>'] | 309 | use: ['!문구 <채팅>'] |
307 | }; | 310 | }; |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -11,7 +11,7 @@ client.once('ready', () => { | ... | @@ -11,7 +11,7 @@ client.once('ready', () => { |
11 | 11 | ||
12 | client.commands = new Discord.Collection(); | 12 | client.commands = new Discord.Collection(); |
13 | client.aliases = new Discord.Collection(); | 13 | client.aliases = new Discord.Collection(); |
14 | -client.category = ['example', 'stationery', 'translate', 'ocr']; | 14 | +client.category = ['Help', 'Stationery', 'Translate', 'Ocr']; |
15 | 15 | ||
16 | fs.readdirSync("./Commands/").forEach(dir => { | 16 | fs.readdirSync("./Commands/").forEach(dir => { |
17 | const Filter = fs.readdirSync(`./Commands/${dir}`).filter(f => f.endsWith(".js")); | 17 | const Filter = fs.readdirSync(`./Commands/${dir}`).filter(f => f.endsWith(".js")); | ... | ... |
-
Please register or login to post a comment