<이전 ver 1.0 개발 포스팅>
https://cocoon1787.tistory.com/741
🛠️ 주요 업데이트 사항
- 메서드 모듈화
- 여러 상품 크롤링
- 코드 리팩터링
📁 디렉터리 구조
🚀 Run Code
server.js
const crawl = require("./crawl.js");
crawl.restock(1145380, "L");
crawl.restock(1520534, "XL");
...
restock 함수의 첫 번째 파라미터는 itemNum, 두 번째 파라미터는 size
터미널에서 다음을 입력.
node server.js
📋 전체 코드
crawl.js
const scheduler = require("node-schedule");
const cheerio = require("cheerio");
const request = require("request");
const kakaoTalk = require("./kakaoTalk.js");
function restock(itemNum, size) {
const schedule = scheduler.scheduleJob("*/2 * * * * *", function () {
let url = "https://store.musinsa.com/app/goods/" + itemNum;
request(url, function (error, response, html) {
if (error) {
throw error;
}
const $ = cheerio.load(html);
const productTitle = $(".product_title em").text();
const option = $(".option1 option");
let map = new Map();
console.log(productTitle);
for (let i = 1; i < option.length; i++) {
// console.log(option[i].attribs.value + " " + option[i].attribs.jaego_yn);
map.set(option[i].attribs.value, option[i].attribs.jaego_yn);
}
console.log("사이즈: " + size);
console.log("재고: " + map.get(size));
if (map.get(size) === "Y") {
const msg = productTitle + " " + size + " 재고있음";
console.log(msg);
kakaoTalk.sendMessage(msg);
schedule.cancel();
}
});
});
}
module.exports = {
restock: restock,
};
kakaoTalk.js
const request = require("request");
const accessToken = "tFcr8OIN47i4J6dgN9JL9FrHHx_6a52OaY4jfAo9dJkAAAF_xjVFJg";
const headers = {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Bearer " + accessToken,
};
function sendMessage(msg) {
const dataString = `template_object={
"object_type": "text",
"text": "${msg}",
"link": {
"web_url": "https://developers.kakao.com",
"mobile_web_url": "https://developers.kakao.com"
},
"button_title": "바로 확인"
}`;
const options = {
url: "https://kapi.kakao.com/v2/api/talk/memo/default/send",
method: "POST",
headers: headers,
body: dataString,
};
request(options, (error, response, body) => {
console.log(response.statusCode);
if (!error && response.statusCode == 200) {
console.log("메시지 전송 완료.");
} else {
console.log(error);
}
});
}
module.exports = {
sendMessage: sendMessage,
};
server.js
const crawl = require("./crawl.js");
crawl.restock(1145380, "L");
crawl.restock(1520534, "LL");
🟩 Node.js 크롤링
crawl.js
const scheduler = require("node-schedule");
const cheerio = require("cheerio");
const request = require("request");
const kakaoTalk = require("./kakaoTalk.js");
function restock(itemNum, size) {
const schedule = scheduler.scheduleJob("*/2 * * * * *", function () {
let url = "https://store.musinsa.com/app/goods/" + itemNum;
request(url, function (error, response, html) {
if (error) {
throw error;
}
const $ = cheerio.load(html);
const productTitle = $(".product_title em").text();
const option = $(".option1 option");
let map = new Map();
console.log(productTitle);
for (let i = 1; i < option.length; i++) {
// console.log(option[i].attribs.value + " " + option[i].attribs.jaego_yn);
map.set(option[i].attribs.value, option[i].attribs.jaego_yn);
}
console.log("사이즈: " + size);
console.log("재고: " + map.get(size));
if (map.get(size) === "Y") {
const msg = productTitle + " " + size + " 재고있음";
console.log(msg);
kakaoTalk.sendMessage(msg);
schedule.cancel();
}
});
});
}
module.exports = {
restock: restock,
};
상품명 출력
const $ = cheerio.load(html);
const productTitle = $(".product_title em").text();
옵션 값들 map으로 저장(key : 사이즈, value : 재고 존재 여부)
const $ = cheerio.load(html);
const productTitle = $(".product_title em").text();
const option = $(".option1 option");
let map = new Map();
console.log(productTitle);
for (let i = 1; i < option.length; i++) {
// console.log(option[i].attribs.value + " " + option[i].attribs.jaego_yn);
map.set(option[i].attribs.value, option[i].attribs.jaego_yn);
}
해당 사이즈의 재고가 있을 경우 카카오톡 메시지 보내기
if (map.get(size) === "Y") {
const msg = productTitle + " " + size + " 재고있음";
console.log(msg);
kakaoTalk.sendMessage(msg);
schedule.cancel();
}
✉️ 카카오톡 메시지 보내기
kakaoTalk.js
const request = require("request");
const accessToken = "tFcr8OIN47i4J6dgN9JL9FrHHx_6a52OaY4jfAo9dJkAAAF_xjVFJg";
const headers = {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Bearer " + accessToken,
};
function sendMessage(msg) {
const dataString = `template_object={
"object_type": "text",
"text": "${msg}",
"link": {
"web_url": "https://developers.kakao.com",
"mobile_web_url": "https://developers.kakao.com"
},
"button_title": "바로 확인"
}`;
const options = {
url: "https://kapi.kakao.com/v2/api/talk/memo/default/send",
method: "POST",
headers: headers,
body: dataString,
};
request(options, (error, response, body) => {
console.log(response.statusCode);
if (!error && response.statusCode == 200) {
console.log("메시지 전송 완료.");
} else {
console.log(error);
}
});
}
module.exports = {
sendMessage: sendMessage,
};
⭐️ 카카오 API 액세스 토큰 발급
kakao developers에서 애플리케이션 생성
https://developers.kakao.com/console/app
애플리케이션을 추가하고 추가한 애플리케이션을 클릭합니다.
애플리케이션을 생성했으니 이제 아래의 URL로 들어가 봅시다.
https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send
요청 - 인증 앱 부분이 developers-sample로 되어있습니다. 오른쪽에 목록 아이콘을 클릭하여 아까 만들어준 애플리케이션으로 변경시켜 줍니다.
그리고 토큰 발급을 받아보려고 하니....
지금 사용해야 할 기능은 talk_message이지만 활성화할 수 없는 상태입니다. talk_message기능을 활성화해주러 가봅시다.
최상단의 "내 애플리케이션"으로 들어가 생성한 애플리케이션을 클릭해주시고
제품 설정 - 카카오 로그인으로 들어가 주세요.
카카오 로그인을 활성화시켜줍니다.
그리고 이번엔 제품 설정 - 카카오 로그인 - 동의 항목으로 들어가 주세요.
맨 아래쪽 접근권한 - 카카오톡 메시지 전송 - 설정
선택 동의로 체크해줍니다.
https://devtalk.kakao.com/t/topic/60237 (선택 동의, 이용 중 동의 차이점)
동의를 하였으니 이제 아까 페이지로 돌아가서 토큰을 발급받아 봅시다.
https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send
talk_message 항목이 활성화되었습니다.
선택항목을 체크하고 "동의하고 계속하기"를 눌러주면 토큰 발급됩니다.
발급받으신 토큰을 kakaoTalk.js의 accessToken이라는 변수에 붙여 넣어 주세요.
💻 테스트
server.js
const crawl = require("./crawl.js");
crawl.restock(1145380, "L");
crawl.restock(1520534, "LL");
<상황>
itemNum : 1145380 -> 플리스 집업 자켓 블랙 / L 사이즈 / 재고 있음
itemNum : 1520534 - > 304-ALT 드라이 무지 긴팔티 블랙 / LL 사이즈 / 재고 없음
scheduler 모듈을 통해 2초마다 크롤링하도록 하였고 크롤링 후 재고가 있을 시에 카카오톡으로 메시지를 보내고 scheduler를 종료하도록 하였습니다.
위의 콘솔 창에서 1145380번 상품의 L사이즈 재고를 확인하고 스케쥴러를 종료하여 1520534번 상품만 크롤링되고 있는 것을 확인할 수 있습니다.
물론 카카오톡 나와의 채팅에서는 "플리스 집업 자켓 블랙 L 재고 있음"이라고 메시지가 하나만 와있게 됩니다.
🐞 Bug
const crawl = require("./crawl.js");
crawl.restock(9999999, "L");
crawl.restock(1520534, "asdasd");
존재하지 않는 itemNum이거나 사이즈 명이 이상할 경우 위와 같이 출력될 수 있으니 꼭 해당 상품의 itemNum과 사이즈명을 확인하시고 크롤링하시길 바랍니다.
https://github.com/K-Junyyy/MUSINSA-CRWALING
'🟩Node.js' 카테고리의 다른 글
[Npm] npm install --save와 --save-dev의 차이점 (0) | 2022.03.01 |
---|---|
[Node.js] request 후 response를 출력할 때 'undefined'가 뜨는 현상 해결 (0) | 2021.11.25 |
[Node.js] Node + Kakao API로 상품 재입고 알림 만들기 (ver 1.0) (0) | 2021.11.14 |
[Node.js] 내장 모듈 Crypto로 해시값 추출하기 (0) | 2021.11.05 |
[Node.js] socket.io 관련 코드 (0) | 2021.11.05 |