init
This commit is contained in:
6
.env.example
Normal file
6
.env.example
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
BIZMAX_ID=JH1204
|
||||||
|
BIZMAX_PASSWORD=12345
|
||||||
|
BIZMAX_RANGE_START=2016-01-01
|
||||||
|
BIZMAX_BATCH_MONTHS=3
|
||||||
|
BIZMAX_BASE_URLS=https://hyun.bizmax.net,https://hyun2.bizmax.net
|
||||||
|
BIZMAX_OUTPUT_DIR=/home/pure13700/project/download/output
|
||||||
144
.gitignore
vendored
Normal file
144
.gitignore
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
.output
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
.temp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Sveltekit cache directory
|
||||||
|
.svelte-kit/
|
||||||
|
|
||||||
|
# vitepress build output
|
||||||
|
**/.vitepress/dist
|
||||||
|
|
||||||
|
# vitepress cache directory
|
||||||
|
**/.vitepress/cache
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# Firebase cache directory
|
||||||
|
.firebase/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
.pnpm-store
|
||||||
|
|
||||||
|
# yarn v3
|
||||||
|
.pnp.*
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/sdks
|
||||||
|
!.yarn/versions
|
||||||
|
|
||||||
|
# Vite files
|
||||||
|
vite.config.js.timestamp-*
|
||||||
|
vite.config.ts.timestamp-*
|
||||||
|
.vite/
|
||||||
813
.playwright-cli/page-2026-04-09T15-43-59-944Z.yml
Normal file
813
.playwright-cli/page-2026-04-09T15-43-59-944Z.yml
Normal file
@@ -0,0 +1,813 @@
|
|||||||
|
- generic [ref=e1]:
|
||||||
|
- generic:
|
||||||
|
- link "상단영역 바로가기" [ref=e2] [cursor=pointer]:
|
||||||
|
- /url: "#topAsideButton"
|
||||||
|
- generic [ref=e3]: 상단영역 바로가기
|
||||||
|
- link "서비스 메뉴 바로가기" [ref=e4] [cursor=pointer]:
|
||||||
|
- /url: "#shortcutArea"
|
||||||
|
- generic [ref=e5]: 서비스 메뉴 바로가기
|
||||||
|
- link "새소식 블록 바로가기" [ref=e6] [cursor=pointer]:
|
||||||
|
- /url: "#newsstand"
|
||||||
|
- generic [ref=e7]: 새소식 블록 바로가기
|
||||||
|
- link "쇼핑 블록 바로가기" [ref=e8] [cursor=pointer]:
|
||||||
|
- /url: "#shopping"
|
||||||
|
- generic [ref=e9]: 쇼핑 블록 바로가기
|
||||||
|
- link "관심사 블록 바로가기" [ref=e10] [cursor=pointer]:
|
||||||
|
- /url: "#feed"
|
||||||
|
- generic [ref=e11]: 관심사 블록 바로가기
|
||||||
|
- link "MY 영역 바로가기" [ref=e12] [cursor=pointer]:
|
||||||
|
- /url: "#account"
|
||||||
|
- generic [ref=e13]: MY 영역 바로가기
|
||||||
|
- link "위젯 보드 바로가기" [ref=e14] [cursor=pointer]:
|
||||||
|
- /url: "#widgetboard"
|
||||||
|
- generic [ref=e15]: 위젯 보드 바로가기
|
||||||
|
- link "보기 설정 바로가기" [ref=e16] [cursor=pointer]:
|
||||||
|
- /url: "#viewSetting"
|
||||||
|
- generic [ref=e17]: 보기 설정 바로가기
|
||||||
|
- generic [ref=e18]:
|
||||||
|
- complementary "웨일 브라우저 설치 안내" [ref=e20]:
|
||||||
|
- generic [ref=e21]:
|
||||||
|
- generic [ref=e22]:
|
||||||
|
- text: 네이버가 만든 브라우저, 웨일을 설치해보세요
|
||||||
|
- link "웨일 설치" [ref=e23] [cursor=pointer]:
|
||||||
|
- /url: https://whale.naver.com/ko?wpid=main_theme1
|
||||||
|
- button "배너 닫기" [ref=e24] [cursor=pointer]:
|
||||||
|
- generic [ref=e25]: 배너 닫기
|
||||||
|
- banner [ref=e26]:
|
||||||
|
- generic [ref=e27]:
|
||||||
|
- generic [ref=e31]:
|
||||||
|
- heading "NAVER NAVER" [level=1] [ref=e32]:
|
||||||
|
- link "NAVER" [ref=e33] [cursor=pointer]:
|
||||||
|
- /url: /
|
||||||
|
- img "NAVER" [ref=e34]
|
||||||
|
- link "NAVER" [ref=e35] [cursor=pointer]:
|
||||||
|
- /url: /
|
||||||
|
- img [ref=e37]
|
||||||
|
- generic [ref=e39]: NAVER
|
||||||
|
- search [ref=e40]:
|
||||||
|
- group "검색" [ref=e41]:
|
||||||
|
- generic [ref=e42]: 검색
|
||||||
|
- combobox "검색어를 입력해 주세요." [active] [ref=e44]
|
||||||
|
- button "검색" [ref=e45] [cursor=pointer]:
|
||||||
|
- img [ref=e47]
|
||||||
|
- generic [ref=e49]: 검색
|
||||||
|
- generic [ref=e50]:
|
||||||
|
- button [ref=e51] [cursor=pointer]
|
||||||
|
- button "자동완성/최근검색어펼치기" [ref=e52] [cursor=pointer]:
|
||||||
|
- generic [ref=e53]: 자동완성/최근검색어펼치기
|
||||||
|
- navigation "주요 서비스" [ref=e54]:
|
||||||
|
- list [ref=e55]:
|
||||||
|
- listitem [ref=e56]:
|
||||||
|
- link "메일" [ref=e57] [cursor=pointer]:
|
||||||
|
- /url: https://mail.naver.com
|
||||||
|
- generic [ref=e59]: 메일
|
||||||
|
- listitem [ref=e60]:
|
||||||
|
- link "카페" [ref=e61] [cursor=pointer]:
|
||||||
|
- /url: https://cafe.naver.com
|
||||||
|
- generic [ref=e63]: 카페
|
||||||
|
- listitem [ref=e64]:
|
||||||
|
- link "블로그" [ref=e65] [cursor=pointer]:
|
||||||
|
- /url: https://blog.naver.com
|
||||||
|
- generic [ref=e67]: 블로그
|
||||||
|
- listitem [ref=e68]:
|
||||||
|
- link "스토어" [ref=e69] [cursor=pointer]:
|
||||||
|
- /url: https://shopping.naver.com/ns/home
|
||||||
|
- generic [ref=e71]: 스토어
|
||||||
|
- listitem [ref=e72]:
|
||||||
|
- link "뉴스" [ref=e73] [cursor=pointer]:
|
||||||
|
- /url: https://news.naver.com/
|
||||||
|
- generic [ref=e75]: 뉴스
|
||||||
|
- listitem [ref=e76]:
|
||||||
|
- link "증권" [ref=e77] [cursor=pointer]:
|
||||||
|
- /url: https://finance.naver.com/
|
||||||
|
- generic [ref=e79]: 증권
|
||||||
|
- listitem [ref=e80]:
|
||||||
|
- link "부동산" [ref=e81] [cursor=pointer]:
|
||||||
|
- /url: https://land.naver.com/
|
||||||
|
- generic [ref=e83]: 부동산
|
||||||
|
- listitem [ref=e84]:
|
||||||
|
- link "지도" [ref=e85] [cursor=pointer]:
|
||||||
|
- /url: https://map.naver.com
|
||||||
|
- generic [ref=e87]: 지도
|
||||||
|
- listitem [ref=e88]:
|
||||||
|
- link "웹툰" [ref=e89] [cursor=pointer]:
|
||||||
|
- /url: https://comic.naver.com
|
||||||
|
- generic [ref=e91]: 웹툰
|
||||||
|
- listitem [ref=e92]:
|
||||||
|
- link "치지직 치지직 추천" [ref=e93] [cursor=pointer]:
|
||||||
|
- /url: https://chzzk.naver.com/?tracking_code=home_recommend
|
||||||
|
- img "치지직" [ref=e95]
|
||||||
|
- generic [ref=e96]: 치지직
|
||||||
|
- generic [ref=e98]: 추천
|
||||||
|
- listitem [ref=e99]:
|
||||||
|
- button "바로가기 펼침" [ref=e100] [cursor=pointer]:
|
||||||
|
- generic [ref=e102]: 바로가기 펼침
|
||||||
|
- button "확장 영역" [ref=e104] [cursor=pointer]:
|
||||||
|
- generic [ref=e105]: 확장 영역
|
||||||
|
- link "페이 바로가기" [ref=e107] [cursor=pointer]:
|
||||||
|
- /url: https://pay.naver.com
|
||||||
|
- generic [ref=e108]: 페이 바로가기
|
||||||
|
- button "알림" [ref=e110] [cursor=pointer]:
|
||||||
|
- generic [ref=e111]: 알림
|
||||||
|
- link "장바구니 알림" [ref=e113] [cursor=pointer]:
|
||||||
|
- /url: https://shopping.naver.com/cart
|
||||||
|
- generic [ref=e114]: 장바구니
|
||||||
|
- generic [ref=e115]: 알림
|
||||||
|
- main [ref=e116]:
|
||||||
|
- generic [ref=e118]:
|
||||||
|
- generic [ref=e119]:
|
||||||
|
- generic [ref=e121]:
|
||||||
|
- generic:
|
||||||
|
- iframe
|
||||||
|
- region "뉴스스탠드" [ref=e122]:
|
||||||
|
- tablist [ref=e125]:
|
||||||
|
- generic [ref=e126]:
|
||||||
|
- tab "뉴스스탠드" [selected] [ref=e127] [cursor=pointer]
|
||||||
|
- tab "언론사편집" [ref=e128] [cursor=pointer]
|
||||||
|
- tab "엔터" [ref=e129] [cursor=pointer]
|
||||||
|
- tab "스포츠 LIVE" [ref=e130] [cursor=pointer]:
|
||||||
|
- text: 스포츠
|
||||||
|
- generic [ref=e131]: LIVE
|
||||||
|
- tab "경제" [ref=e132] [cursor=pointer]
|
||||||
|
- tab "쇼핑투데이" [ref=e133] [cursor=pointer]
|
||||||
|
- generic [ref=e134]:
|
||||||
|
- button "전체언론사" [ref=e135] [cursor=pointer]: 전체언론사
|
||||||
|
- generic [ref=e137]:
|
||||||
|
- link "연합뉴스" [ref=e138] [cursor=pointer]:
|
||||||
|
- /url: https://news.naver.com/main/list.naver?mode=LPOD&mid=sec&sid1=001&sid2=140&oid=001&isYeonhapFlash=Y
|
||||||
|
- link "\"이란, 휴전중 호르무즈 통행 하루 15척 이하로 제한\"" [ref=e143] [cursor=pointer]:
|
||||||
|
- /url: https://news.naver.com/main/list.naver?mode=LPOD&mid=sec&sid1=001&sid2=140&oid=001&isYeonhapFlash=Y&aid=0016013237
|
||||||
|
- generic [ref=e144]:
|
||||||
|
- link "뉴스스탠드" [ref=e145] [cursor=pointer]:
|
||||||
|
- /url: https://newsstand.naver.com/
|
||||||
|
- link "뉴스홈" [ref=e146] [cursor=pointer]:
|
||||||
|
- /url: https://news.naver.com/
|
||||||
|
- tabpanel [ref=e147]:
|
||||||
|
- generic [ref=e158]:
|
||||||
|
- link "MBC" [ref=e160] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "MBC" [ref=e161]
|
||||||
|
- link "OSEN" [ref=e163] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "OSEN" [ref=e164]
|
||||||
|
- link "국민일보" [ref=e166] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "국민일보" [ref=e167]
|
||||||
|
- link "스포츠서울" [ref=e169] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "스포츠서울" [ref=e170]
|
||||||
|
- link "중앙데일리" [ref=e172] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "중앙데일리" [ref=e173]
|
||||||
|
- link "일간스포츠" [ref=e175] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "일간스포츠" [ref=e176]
|
||||||
|
- link "파이낸셜뉴스" [ref=e178] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "파이낸셜뉴스" [ref=e179]
|
||||||
|
- link "노컷뉴스" [ref=e181] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "노컷뉴스" [ref=e182]
|
||||||
|
- link "조선비즈" [ref=e184] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "조선비즈" [ref=e185]
|
||||||
|
- link "연합뉴스TV" [ref=e187] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "연합뉴스TV" [ref=e188]
|
||||||
|
- link "한국일보" [ref=e190] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "한국일보" [ref=e191]
|
||||||
|
- link "아이뉴스24" [ref=e193] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "아이뉴스24" [ref=e194]
|
||||||
|
- link "뉴데일리" [ref=e196] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "뉴데일리" [ref=e197]
|
||||||
|
- link "지디넷코리아" [ref=e199] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "지디넷코리아" [ref=e200]
|
||||||
|
- link "코리아헤럴드" [ref=e202] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "코리아헤럴드" [ref=e203]
|
||||||
|
- link "경인일보" [ref=e205] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "경인일보" [ref=e206]
|
||||||
|
- link "중부일보" [ref=e208] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "중부일보" [ref=e209]
|
||||||
|
- link "기호일보" [ref=e211] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "기호일보" [ref=e212]
|
||||||
|
- link "시사저널이코노미" [ref=e214] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "시사저널이코노미" [ref=e215]
|
||||||
|
- link "월간중앙" [ref=e217] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "월간중앙" [ref=e218]
|
||||||
|
- link "넥스트데일리" [ref=e220] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "넥스트데일리" [ref=e221]
|
||||||
|
- link "쿠키뉴스" [ref=e223] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "쿠키뉴스" [ref=e224]
|
||||||
|
- link "에너지경제" [ref=e226] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "에너지경제" [ref=e227]
|
||||||
|
- link "뉴스토마토" [ref=e229] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- img "뉴스토마토" [ref=e230]
|
||||||
|
- generic [ref=e231]:
|
||||||
|
- radiogroup [ref=e232]:
|
||||||
|
- radio "리스트형" [ref=e233] [cursor=pointer]:
|
||||||
|
- generic [ref=e234]: 리스트형
|
||||||
|
- radio "썸네일형" [checked] [ref=e235] [cursor=pointer]:
|
||||||
|
- generic [ref=e236]: 썸네일형
|
||||||
|
- button "이전 페이지" [ref=e237] [cursor=pointer]:
|
||||||
|
- generic [ref=e238]: 이전 페이지
|
||||||
|
- generic [ref=e239]:
|
||||||
|
- generic [ref=e240]: 언론사 더보기
|
||||||
|
- generic [ref=e241]:
|
||||||
|
- text: "1"
|
||||||
|
- generic [ref=e242]: 페이지
|
||||||
|
- generic [ref=e243]:
|
||||||
|
- generic [ref=e244]: 전체
|
||||||
|
- text: /4
|
||||||
|
- button "다음 페이지" [ref=e245] [cursor=pointer]:
|
||||||
|
- generic [ref=e246]: 다음 페이지
|
||||||
|
- region "쇼핑" [ref=e247]:
|
||||||
|
- iframe [ref=e248]:
|
||||||
|
- tablist [ref=f2e5]:
|
||||||
|
- tab "쇼핑" [selected] [ref=f2e6] [cursor=pointer]
|
||||||
|
- tab "맨즈" [ref=f2e7] [cursor=pointer]
|
||||||
|
- tab "브랜드샵" [ref=f2e8] [cursor=pointer]
|
||||||
|
- tab "추천핫딜" [ref=f2e9] [cursor=pointer]
|
||||||
|
- tab "MY추천" [ref=f2e10] [cursor=pointer]
|
||||||
|
- tab "쇼핑라이브" [ref=f2e11] [cursor=pointer]
|
||||||
|
- region "추천 관심사" [ref=e249]:
|
||||||
|
- generic [ref=e251]:
|
||||||
|
- tablist [ref=e252]:
|
||||||
|
- tab "추천" [ref=e254] [cursor=pointer]
|
||||||
|
- tab "카테크" [ref=e255] [cursor=pointer]
|
||||||
|
- tab "웹툰" [ref=e256] [cursor=pointer]
|
||||||
|
- tab "패션뷰티" [ref=e257] [cursor=pointer]
|
||||||
|
- tab "리빙푸드" [ref=e258] [cursor=pointer]
|
||||||
|
- tab "책방" [ref=e259] [cursor=pointer]
|
||||||
|
- tab "지식" [ref=e260] [cursor=pointer]
|
||||||
|
- tab "건강" [ref=e261] [cursor=pointer]
|
||||||
|
- tab "게임" [ref=e262] [cursor=pointer]
|
||||||
|
- link "구독홈" [ref=e263] [cursor=pointer]:
|
||||||
|
- /url: https://m.naver.com/mysubs?mode=pc
|
||||||
|
- tabpanel [ref=e264]:
|
||||||
|
- list [ref=e266]:
|
||||||
|
- listitem [ref=e267]:
|
||||||
|
- link "노리 후리가케주먹밥 도시락 명란마요 참치마요 주먹밥 만드는법 뵤뵤" [ref=e268] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/byobyoblog/contents/internal/825269494747008
|
||||||
|
- generic [ref=e271]:
|
||||||
|
- strong [ref=e272]: 노리 후리가케주먹밥 도시락 명란마요 참치마요 주먹밥 만드는법
|
||||||
|
- generic [ref=e274]: 뵤뵤
|
||||||
|
- listitem [ref=e276]:
|
||||||
|
- link "닭가슴살볶음밥 만드는법 닭가슴살다이어트요리 다이어트식단 닭가슴살요리 popo" [ref=e277] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/popo/contents/internal/851094056034976
|
||||||
|
- generic [ref=e280]:
|
||||||
|
- strong [ref=e281]: 닭가슴살볶음밥 만드는법 닭가슴살다이어트요리 다이어트식단 닭가슴살요리
|
||||||
|
- generic [ref=e283]: popo
|
||||||
|
- listitem [ref=e285]:
|
||||||
|
- link "양배추당근라페 만들기 다이어트에 좋은 샐러드 슈슈냥" [ref=e286] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/shushu321/contents/internal/857944040379200
|
||||||
|
- generic [ref=e289]:
|
||||||
|
- strong [ref=e290]: 양배추당근라페 만들기 다이어트에 좋은 샐러드
|
||||||
|
- generic [ref=e292]: 슈슈냥
|
||||||
|
- listitem [ref=e294]
|
||||||
|
- listitem [ref=e295]:
|
||||||
|
- link "성시경 부추당면잡채 만들기 원팬잡채 레시피 냉동 대패삼겹살 잡채밥 요리 쑨여사" [ref=e296] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/happy4305/contents/internal/857448295249184
|
||||||
|
- generic [ref=e299]:
|
||||||
|
- strong [ref=e300]: 성시경 부추당면잡채 만들기 원팬잡채 레시피 냉동 대패삼겹살 잡채밥 요리
|
||||||
|
- generic [ref=e302]: 쑨여사
|
||||||
|
- listitem [ref=e304]:
|
||||||
|
- link "원팬 오일파스타 만들기 새우 알리오 올리오 파스타 소스 레시피 웅이맘" [ref=e305] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/pingu528/contents/internal/844575116092576
|
||||||
|
- generic [ref=e308]:
|
||||||
|
- strong [ref=e309]: 원팬 오일파스타 만들기 새우 알리오 올리오 파스타 소스 레시피
|
||||||
|
- generic [ref=e311]: 웅이맘
|
||||||
|
- listitem [ref=e313]:
|
||||||
|
- link "명란 오일파스타 레시피 원팬 명란파스타 만들기 투우맘" [ref=e314] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/wookyungmom/contents/internal/852914784916640
|
||||||
|
- generic [ref=e317]:
|
||||||
|
- strong [ref=e318]: 명란 오일파스타 레시피 원팬 명란파스타 만들기
|
||||||
|
- generic [ref=e320]: 투우맘
|
||||||
|
- listitem [ref=e322]:
|
||||||
|
- link "양배추참치덮밥 다이어트 양배추요리 참치 양배추덮밥 레시피 라임샴푸" [ref=e323] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/limeshampoo/contents/internal/842632039113696
|
||||||
|
- generic [ref=e326]:
|
||||||
|
- strong [ref=e327]: 양배추참치덮밥 다이어트 양배추요리 참치 양배추덮밥 레시피
|
||||||
|
- generic [ref=e329]: 라임샴푸
|
||||||
|
- listitem [ref=e331]:
|
||||||
|
- link "부추계란볶음 덮밥 만들기 간단한 부추요리 인천서현" [ref=e332] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/mjh0712/contents/internal/859069732262880
|
||||||
|
- generic [ref=e335]:
|
||||||
|
- strong [ref=e336]: 부추계란볶음 덮밥 만들기 간단한 부추요리
|
||||||
|
- generic [ref=e338]: 인천서현
|
||||||
|
- generic [ref=e340]:
|
||||||
|
- strong [ref=e342]: 테마별 레시피
|
||||||
|
- list [ref=e344]:
|
||||||
|
- listitem [ref=e345]:
|
||||||
|
- link "#직장인도시락 직장인 점심도시락메뉴 일주일 샐러드 다이어트식단 간단한 도시락만들기 윌리쥴리맘" [ref=e346] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/a0910102/contents/internal/856749320614720
|
||||||
|
- generic [ref=e349]:
|
||||||
|
- generic [ref=e350]: "#직장인도시락"
|
||||||
|
- strong [ref=e351]: 직장인 점심도시락메뉴 일주일 샐러드 다이어트식단 간단한 도시락만들기
|
||||||
|
- generic [ref=e353]: 윌리쥴리맘
|
||||||
|
- listitem [ref=e355]:
|
||||||
|
- link "#꽈리고추무침 꽈리고추찜 레시피 꽈리고추 무침 요리 가정식 반찬거리 레즐리" [ref=e356] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/peace8012/contents/internal/838171749762272
|
||||||
|
- generic [ref=e359]:
|
||||||
|
- generic [ref=e360]: "#꽈리고추무침"
|
||||||
|
- strong [ref=e361]: 꽈리고추찜 레시피 꽈리고추 무침 요리 가정식 반찬거리
|
||||||
|
- generic [ref=e363]: 레즐리
|
||||||
|
- listitem [ref=e365]:
|
||||||
|
- link "#아침밥 버터 간장계란밥 레시피 계란밥 아침밥 레지나" [ref=e366] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/lalacucina/contents/internal/846385783219360
|
||||||
|
- generic [ref=e369]:
|
||||||
|
- generic [ref=e370]: "#아침밥"
|
||||||
|
- strong [ref=e371]: 버터 간장계란밥 레시피 계란밥 아침밥
|
||||||
|
- generic [ref=e373]: 레지나
|
||||||
|
- listitem [ref=e375]:
|
||||||
|
- link "#스팸감자채볶음 감자채볶음 만들기 레시피 스팸 감자볶음 만드는 법 레즐리" [ref=e376] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/peace8012/contents/internal/855542825091744
|
||||||
|
- generic [ref=e379]:
|
||||||
|
- generic [ref=e380]: "#스팸감자채볶음"
|
||||||
|
- strong [ref=e381]: 감자채볶음 만들기 레시피 스팸 감자볶음 만드는 법
|
||||||
|
- generic [ref=e383]: 레즐리
|
||||||
|
- listitem [ref=e385]:
|
||||||
|
- link "#꽈리고추무침 꽈리고추찜 레시피 양념 꽈리고추 무침 요리 만드는 법 봉스" [ref=e386] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/bongsrecipe/contents/internal/855051303388224
|
||||||
|
- generic [ref=e389]:
|
||||||
|
- generic [ref=e390]: "#꽈리고추무침"
|
||||||
|
- strong [ref=e391]: 꽈리고추찜 레시피 양념 꽈리고추 무침 요리 만드는 법
|
||||||
|
- generic [ref=e393]: 봉스
|
||||||
|
- listitem [ref=e395]:
|
||||||
|
- link "#간단한도시락 삼각김밥으로 간단한 도시락 만들기, 간단김밥으로 추천 안녕하다" [ref=e396] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/annyeong/contents/internal/844365422920480
|
||||||
|
- generic [ref=e399]:
|
||||||
|
- generic [ref=e400]: "#간단한도시락"
|
||||||
|
- strong [ref=e401]: 삼각김밥으로 간단한 도시락 만들기, 간단김밥으로 추천
|
||||||
|
- generic [ref=e403]: 안녕하다
|
||||||
|
- listitem [ref=e405]:
|
||||||
|
- link "#홈베이킹 땅콩버터 요리 땅콩크림빵 만들기 초보 홈베이킹 뚜루" [ref=e406] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/2min_love/contents/internal/841020666123232
|
||||||
|
- generic [ref=e409]:
|
||||||
|
- generic [ref=e410]: "#홈베이킹"
|
||||||
|
- strong [ref=e411]: 땅콩버터 요리 땅콩크림빵 만들기 초보 홈베이킹
|
||||||
|
- generic [ref=e413]: 뚜루
|
||||||
|
- listitem [ref=e415]:
|
||||||
|
- link "#직장인도시락 직장인남편 점심도시락 만들기 127주차 기록남기기 하니맘" [ref=e416] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/johan0626/contents/internal/859653992072320
|
||||||
|
- generic [ref=e419]:
|
||||||
|
- generic [ref=e420]: "#직장인도시락"
|
||||||
|
- strong [ref=e421]: 직장인남편 점심도시락 만들기 127주차 기록남기기
|
||||||
|
- generic [ref=e423]: 하니맘
|
||||||
|
- listitem [ref=e425]:
|
||||||
|
- link "#홈베이킹 스모어크래커 만들기ㅣS'more cracker recipeㅣ홈베이킹 효니" [ref=e426] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/hyuni_525/contents/internal/860060428370752
|
||||||
|
- generic [ref=e429]:
|
||||||
|
- generic [ref=e430]: "#홈베이킹"
|
||||||
|
- strong [ref=e431]: 스모어크래커 만들기ㅣS'more cracker recipeㅣ홈베이킹
|
||||||
|
- generic [ref=e433]: 효니
|
||||||
|
- listitem [ref=e435]:
|
||||||
|
- link "#편스토랑레시피 간단 제육볶음 편스토랑 김강우제육볶음 레시피 앞다리살 양념 심플민" [ref=e436] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/simplemin_life/contents/internal/859765239596224
|
||||||
|
- generic [ref=e439]:
|
||||||
|
- generic [ref=e440]: "#편스토랑레시피"
|
||||||
|
- strong [ref=e441]: 간단 제육볶음 편스토랑 김강우제육볶음 레시피 앞다리살 양념
|
||||||
|
- generic [ref=e443]: 심플민
|
||||||
|
- listitem [ref=e445]:
|
||||||
|
- link "#아침밥 간단한 아침밥 김가루 주먹밥 레시피 만들기 찬밥 요리 숲 집밥" [ref=e446] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/forest0405/contents/internal/859643515732768
|
||||||
|
- generic [ref=e449]:
|
||||||
|
- generic [ref=e450]: "#아침밥"
|
||||||
|
- strong [ref=e451]: 간단한 아침밥 김가루 주먹밥 레시피 만들기 찬밥 요리
|
||||||
|
- generic [ref=e453]: 숲 집밥
|
||||||
|
- listitem [ref=e455]:
|
||||||
|
- link "#원팬토스트 간단 토스트 레시피 식빵 계란토스트 원팬으로 간단하게! 리베" [ref=e456] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/sbmn0313/contents/internal/856973790860256
|
||||||
|
- generic [ref=e459]:
|
||||||
|
- generic [ref=e460]: "#원팬토스트"
|
||||||
|
- strong [ref=e461]: 간단 토스트 레시피 식빵 계란토스트 원팬으로 간단하게!
|
||||||
|
- generic [ref=e463]: 리베
|
||||||
|
- listitem [ref=e465]:
|
||||||
|
- link "#스팸감자채볶음 감자채볶음 입맛 살리는 스팸감자채볶음 만드는 법! 간단한 밑반찬 만들기 미소순이" [ref=e466] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/misosooni/contents/internal/838175943390016
|
||||||
|
- generic [ref=e469]:
|
||||||
|
- generic [ref=e470]: "#스팸감자채볶음"
|
||||||
|
- strong [ref=e471]: 감자채볶음 입맛 살리는 스팸감자채볶음 만드는 법! 간단한 밑반찬 만들기
|
||||||
|
- generic [ref=e473]: 미소순이
|
||||||
|
- listitem [ref=e475]:
|
||||||
|
- link "#저녁밥상 여름방학 주간밥상 일주일 저녁밥상 집밥메뉴 추천 오늘뭐먹지 윤줌마" [ref=e476] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/koyunj0723/contents/internal/852943309222880
|
||||||
|
- generic [ref=e479]:
|
||||||
|
- generic [ref=e480]: "#저녁밥상"
|
||||||
|
- strong [ref=e481]: 여름방학 주간밥상 일주일 저녁밥상 집밥메뉴 추천 오늘뭐먹지
|
||||||
|
- generic [ref=e483]: 윤줌마
|
||||||
|
- listitem [ref=e485]:
|
||||||
|
- link "#원팬토스트 원팬 토스트 만들기 통밀 또띠아 다이어트 양배추 요리 꼬마츄츄" [ref=e486] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/baby0817/contents/internal/856786409456928
|
||||||
|
- generic [ref=e489]:
|
||||||
|
- generic [ref=e490]: "#원팬토스트"
|
||||||
|
- strong [ref=e491]: 원팬 토스트 만들기 통밀 또띠아 다이어트 양배추 요리
|
||||||
|
- generic [ref=e493]: 꼬마츄츄
|
||||||
|
- listitem [ref=e495]:
|
||||||
|
- link "#아침밥 전자레인지 계란밥 레시피 간장계란밥 간단한아침메뉴 뽕림이" [ref=e496] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/yoririm/contents/internal/856940888498976
|
||||||
|
- generic [ref=e499]:
|
||||||
|
- generic [ref=e500]: "#아침밥"
|
||||||
|
- strong [ref=e501]: 전자레인지 계란밥 레시피 간장계란밥 간단한아침메뉴
|
||||||
|
- generic [ref=e503]: 뽕림이
|
||||||
|
- listitem [ref=e505]:
|
||||||
|
- link "#간단한아침국 코인육수 계란국 끓이는법 간단한 아침국 감자계란국 레시피 맛있는 찰나" [ref=e506] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/ckfsk07/contents/internal/859975465555232
|
||||||
|
- generic [ref=e509]:
|
||||||
|
- generic [ref=e510]: "#간단한아침국"
|
||||||
|
- strong [ref=e511]: 코인육수 계란국 끓이는법 간단한 아침국 감자계란국 레시피
|
||||||
|
- generic [ref=e513]: 맛있는 찰나
|
||||||
|
- listitem [ref=e515]:
|
||||||
|
- link "#원팬토스트 길거리토스트 만들기 레시피 식빵 계란토스트 원팬 햄치즈 토스트 라임샴푸" [ref=e516] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/limeshampoo/contents/internal/843746572170400
|
||||||
|
- generic [ref=e519]:
|
||||||
|
- generic [ref=e520]: "#원팬토스트"
|
||||||
|
- strong [ref=e521]: 길거리토스트 만들기 레시피 식빵 계란토스트 원팬 햄치즈 토스트
|
||||||
|
- generic [ref=e523]: 라임샴푸
|
||||||
|
- listitem [ref=e525]:
|
||||||
|
- link "#초간단요리 애호박소고기볶음레시피 애호박덮밥 초간단요리 험나니" [ref=e526] [cursor=pointer]:
|
||||||
|
- /url: https://in.naver.com/sdhl1004/contents/internal/850117784413376
|
||||||
|
- generic [ref=e529]:
|
||||||
|
- generic [ref=e530]: "#초간단요리"
|
||||||
|
- strong [ref=e531]: 애호박소고기볶음레시피 애호박덮밥 초간단요리
|
||||||
|
- generic [ref=e533]: 험나니
|
||||||
|
- listitem [ref=e535]:
|
||||||
|
- link "#다이어트계란요리 간단한 아침메뉴 빵없는 계란토스트 다이어트 계란요리 제인JANE" [ref=e536] [cursor=pointer]:
|
||||||
|
- /url: https://blog.naver.com/kyjsp/223979446869
|
||||||
|
- generic [ref=e539]:
|
||||||
|
- generic [ref=e540]: "#다이어트계란요리"
|
||||||
|
- strong [ref=e541]: 간단한 아침메뉴 빵없는 계란토스트 다이어트 계란요리
|
||||||
|
- generic [ref=e543]: 제인JANE
|
||||||
|
- button "다음 페이지" [ref=e545] [cursor=pointer]:
|
||||||
|
- generic [ref=e546]: 다음 페이지
|
||||||
|
- button "펼쳐보기" [ref=e548] [cursor=pointer]: 펼쳐보기
|
||||||
|
- generic [ref=e554]:
|
||||||
|
- region "로그인 정보" [ref=e555]:
|
||||||
|
- generic [ref=e556]:
|
||||||
|
- paragraph [ref=e557]: 네이버를 더 안전하고 편리하게 이용하세요
|
||||||
|
- link "NAVER 로그인" [ref=e558] [cursor=pointer]:
|
||||||
|
- /url: https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/
|
||||||
|
- generic [ref=e560]: NAVER
|
||||||
|
- text: 로그인
|
||||||
|
- generic [ref=e561]:
|
||||||
|
- link "아이디 찾기" [ref=e562] [cursor=pointer]:
|
||||||
|
- /url: https://nid.naver.com/user2/api/route?m=routeIdInquiry
|
||||||
|
- link "비밀번호 찾기" [ref=e563] [cursor=pointer]:
|
||||||
|
- /url: https://nid.naver.com/user2/api/route?m=routePwInquiry
|
||||||
|
- link "회원가입" [ref=e564] [cursor=pointer]:
|
||||||
|
- /url: https://nid.naver.com/nidregister.form?url=https%3A%2F%2Fwww.naver.com
|
||||||
|
- iframe [ref=e570]:
|
||||||
|
- generic [active]:
|
||||||
|
- main
|
||||||
|
- alert [ref=f3e1]
|
||||||
|
- region "날씨" [ref=e571]:
|
||||||
|
- generic [ref=e572]:
|
||||||
|
- generic [ref=e573]:
|
||||||
|
- link "날씨" [ref=e574] [cursor=pointer]:
|
||||||
|
- /url: https://weather.naver.com/
|
||||||
|
- link "예보 비교" [ref=e575] [cursor=pointer]:
|
||||||
|
- /url: https://weather.naver.com/compare/02285105
|
||||||
|
- generic [ref=e576]: 고양시 마두동
|
||||||
|
- generic [ref=e577]:
|
||||||
|
- generic [ref=e578]:
|
||||||
|
- link "12.1° 비 최저기온 10° 최고기온 15°" [ref=e579] [cursor=pointer]:
|
||||||
|
- /url: https://weather.naver.com/today/02285105?cpName=KMA
|
||||||
|
- generic [ref=e582]:
|
||||||
|
- text: 12.1°
|
||||||
|
- generic [ref=e583]: 비
|
||||||
|
- generic [ref=e584]:
|
||||||
|
- generic [ref=e585]:
|
||||||
|
- generic [ref=e586]: 최저기온
|
||||||
|
- text: 10°
|
||||||
|
- generic [ref=e587]:
|
||||||
|
- generic [ref=e588]: 최고기온
|
||||||
|
- text: 15°
|
||||||
|
- link "미세좋음 초미세좋음" [ref=e589] [cursor=pointer]:
|
||||||
|
- /url: https://weather.naver.com/air/02285105?cpName=KMA
|
||||||
|
- generic [ref=e590]: 미세좋음
|
||||||
|
- generic [ref=e591]: 초미세좋음
|
||||||
|
- link "1시 비 12° 3 구름많음 11° 5 흐림 10° 7 흐림 10° 9 구름많음 10°" [ref=e593] [cursor=pointer]:
|
||||||
|
- /url: https://weather.naver.com/today/02285105?cpName=KMA
|
||||||
|
- list [ref=e596]:
|
||||||
|
- listitem [ref=e597]:
|
||||||
|
- generic [ref=e598]: 1시
|
||||||
|
- generic [ref=e600]: 비
|
||||||
|
- generic [ref=e601]: 12°
|
||||||
|
- listitem [ref=e602]:
|
||||||
|
- generic [ref=e603]: "3"
|
||||||
|
- generic [ref=e605]: 구름많음
|
||||||
|
- generic [ref=e606]: 11°
|
||||||
|
- listitem [ref=e607]:
|
||||||
|
- generic [ref=e608]: "5"
|
||||||
|
- generic [ref=e610]: 흐림
|
||||||
|
- generic [ref=e611]: 10°
|
||||||
|
- listitem [ref=e612]:
|
||||||
|
- generic [ref=e613]: "7"
|
||||||
|
- generic [ref=e615]: 흐림
|
||||||
|
- generic [ref=e616]: 10°
|
||||||
|
- listitem [ref=e617]:
|
||||||
|
- generic [ref=e618]: "9"
|
||||||
|
- generic [ref=e620]: 구름많음
|
||||||
|
- generic [ref=e621]: 10°
|
||||||
|
- region "증시" [ref=e622]:
|
||||||
|
- generic [ref=e623]:
|
||||||
|
- generic [ref=e624]:
|
||||||
|
- link "증시" [ref=e625] [cursor=pointer]:
|
||||||
|
- /url: https://finance.naver.com/
|
||||||
|
- button "정보 더보기" [ref=e626] [cursor=pointer]:
|
||||||
|
- generic [ref=e627]: 정보 더보기
|
||||||
|
- generic [ref=e628]:
|
||||||
|
- text: 04.10. 00:43
|
||||||
|
- button "새로고침" [ref=e629] [cursor=pointer]:
|
||||||
|
- generic [ref=e630]: 새로고침
|
||||||
|
- generic [ref=e631]:
|
||||||
|
- link "다우존스 47,988.88 상승 78.96+0.16%" [ref=e635] [cursor=pointer]:
|
||||||
|
- /url: https://finance.naver.com/world/sise.nhn?symbol=DJI@DJI
|
||||||
|
- generic [ref=e636]:
|
||||||
|
- generic [ref=e637]: 다우존스
|
||||||
|
- generic [ref=e638]: 47,988.88
|
||||||
|
- generic [ref=e639]:
|
||||||
|
- generic [ref=e641]: 상승
|
||||||
|
- text: "78.96"
|
||||||
|
- generic [ref=e642]: +0.16%
|
||||||
|
- list [ref=e645]:
|
||||||
|
- listitem [ref=e646]:
|
||||||
|
- link "삼성전자 하락 3.09% 204,000" [ref=e647] [cursor=pointer]:
|
||||||
|
- /url: https://finance.naver.com/item/main.naver?code=005930
|
||||||
|
- generic [ref=e648]: 삼성전자
|
||||||
|
- generic [ref=e649]:
|
||||||
|
- generic [ref=e651]: 하락
|
||||||
|
- generic [ref=e652]: 3.09%
|
||||||
|
- text: 204,000
|
||||||
|
- listitem [ref=e653]:
|
||||||
|
- link "SK하이닉스 하락 3.39% 998,000" [ref=e654] [cursor=pointer]:
|
||||||
|
- /url: https://finance.naver.com/item/main.naver?code=000660
|
||||||
|
- generic [ref=e655]: SK하이닉스
|
||||||
|
- generic [ref=e656]:
|
||||||
|
- generic [ref=e658]: 하락
|
||||||
|
- generic [ref=e659]: 3.39%
|
||||||
|
- text: 998,000
|
||||||
|
- listitem [ref=e660]:
|
||||||
|
- link "삼천당제약 상승 3.92% 504,000" [ref=e661] [cursor=pointer]:
|
||||||
|
- /url: https://finance.naver.com/item/main.naver?code=000250
|
||||||
|
- generic [ref=e662]: 삼천당제약
|
||||||
|
- generic [ref=e663]:
|
||||||
|
- generic [ref=e665]: 상승
|
||||||
|
- generic [ref=e666]: 3.92%
|
||||||
|
- text: 504,000
|
||||||
|
- listitem [ref=e667]:
|
||||||
|
- link "인기종목 더보기" [ref=e668] [cursor=pointer]:
|
||||||
|
- /url: https://finance.naver.com/sise/lastsearch2.naver
|
||||||
|
- region "위젯" [ref=e669]:
|
||||||
|
- generic [ref=e670]: 위젯 보드
|
||||||
|
- generic [ref=e671]:
|
||||||
|
- generic [ref=e672]:
|
||||||
|
- generic [ref=e673]:
|
||||||
|
- generic [ref=e674]:
|
||||||
|
- generic [ref=e676]: 캘린더
|
||||||
|
- generic [ref=e678]:
|
||||||
|
- text: "4.10"
|
||||||
|
- generic [ref=e679]: 금
|
||||||
|
- link "로그인하기":
|
||||||
|
- /url: https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/?to=widget
|
||||||
|
- generic [ref=e680] [cursor=pointer]: 로그인하기
|
||||||
|
- link "2026년 4월 캘린더 - 이번 달의 일정을 날짜별로 확인할 수 있는 표입니다. 각 셀에는 날짜와 해당 일정이 포함됩니다." [ref=e681] [cursor=pointer]:
|
||||||
|
- /url: https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/?to=widget
|
||||||
|
- table "2026년 4월 캘린더 - 이번 달의 일정을 날짜별로 확인할 수 있는 표입니다. 각 셀에는 날짜와 해당 일정이 포함됩니다." [ref=e682]:
|
||||||
|
- caption [ref=e683]: 2026년 4월 캘린더 - 이번 달의 일정을 날짜별로 확인할 수 있는 표입니다. 각 셀에는 날짜와 해당 일정이 포함됩니다.
|
||||||
|
- rowgroup [ref=e684]:
|
||||||
|
- row "일 월 화 수 목 금 토" [ref=e685]:
|
||||||
|
- columnheader "일" [ref=e686]
|
||||||
|
- columnheader "월" [ref=e687]
|
||||||
|
- columnheader "화" [ref=e688]
|
||||||
|
- columnheader "수" [ref=e689]
|
||||||
|
- columnheader "목" [ref=e690]
|
||||||
|
- columnheader "금" [ref=e691]
|
||||||
|
- columnheader "토" [ref=e692]
|
||||||
|
- rowgroup [ref=e693]:
|
||||||
|
- row "29 30 31 1 2 3 4" [ref=e694]:
|
||||||
|
- cell "29" [ref=e695]
|
||||||
|
- cell "30" [ref=e696]
|
||||||
|
- cell "31" [ref=e697]
|
||||||
|
- cell "1" [ref=e698]
|
||||||
|
- cell "2" [ref=e699]
|
||||||
|
- cell "3" [ref=e700]
|
||||||
|
- cell "4" [ref=e701]
|
||||||
|
- row "5 6 7 8 9 10 11" [ref=e702]:
|
||||||
|
- cell "5" [ref=e703]
|
||||||
|
- cell "6" [ref=e704]
|
||||||
|
- cell "7" [ref=e705]
|
||||||
|
- cell "8" [ref=e706]
|
||||||
|
- cell "9" [ref=e707]
|
||||||
|
- cell "10" [ref=e708]
|
||||||
|
- cell "11" [ref=e709]
|
||||||
|
- row "12 13 14 15 16 17 18" [ref=e710]:
|
||||||
|
- cell "12" [ref=e711]
|
||||||
|
- cell "13" [ref=e712]
|
||||||
|
- cell "14" [ref=e713]
|
||||||
|
- cell "15" [ref=e714]
|
||||||
|
- cell "16" [ref=e715]
|
||||||
|
- cell "17" [ref=e716]
|
||||||
|
- cell "18" [ref=e717]
|
||||||
|
- row "19 20 21 22 23 24 25" [ref=e718]:
|
||||||
|
- cell "19" [ref=e719]
|
||||||
|
- cell "20" [ref=e720]
|
||||||
|
- cell "21" [ref=e721]
|
||||||
|
- cell "22" [ref=e722]
|
||||||
|
- cell "23" [ref=e723]
|
||||||
|
- cell "24" [ref=e724]
|
||||||
|
- cell "25" [ref=e725]
|
||||||
|
- row "26 27 28 29 30 1 2" [ref=e726]:
|
||||||
|
- cell "26" [ref=e727]
|
||||||
|
- cell "27" [ref=e728]
|
||||||
|
- cell "28" [ref=e729]
|
||||||
|
- cell "29" [ref=e730]
|
||||||
|
- cell "30" [ref=e731]
|
||||||
|
- cell "1" [ref=e732]
|
||||||
|
- cell "2" [ref=e733]
|
||||||
|
- generic [ref=e734]:
|
||||||
|
- generic [ref=e735]:
|
||||||
|
- generic [ref=e737]: VIBE
|
||||||
|
- generic [ref=e738]: 십자군전쟁이란?
|
||||||
|
- button "다른 추천 보기" [ref=e739] [cursor=pointer]
|
||||||
|
- list [ref=e740]:
|
||||||
|
- listitem [ref=e741]:
|
||||||
|
- link "1회 - 200년의 종교 전쟁! 지금, 시작합니다. 재생" [ref=e742] [cursor=pointer]:
|
||||||
|
- /url: https://vibe.naver.com/audio_player?curationId=1027&contentId=CH_4910_EP_405&audioContentId=CH_4910_EP_405
|
||||||
|
- strong [ref=e744]: 1회 - 200년의 종교 전쟁! 지금, 시작합니다.
|
||||||
|
- generic [ref=e746]: 재생
|
||||||
|
- listitem [ref=e747]:
|
||||||
|
- link "2회 - 균형 잡힌 관점으로 전쟁을 알려면? 이것부터! 재생" [ref=e748] [cursor=pointer]:
|
||||||
|
- /url: https://vibe.naver.com/audio_player?curationId=1027&contentId=CH_4910_EP_406&audioContentId=CH_4910_EP_406
|
||||||
|
- strong [ref=e750]: 2회 - 균형 잡힌 관점으로 전쟁을 알려면? 이것부터!
|
||||||
|
- generic [ref=e752]: 재생
|
||||||
|
- listitem [ref=e753]:
|
||||||
|
- 'link "3회 - 셀주크 제국과 동로마의 첫 전투, 결과는? #만지케르트전투 재생" [ref=e754] [cursor=pointer]':
|
||||||
|
- /url: https://vibe.naver.com/audio_player?curationId=1027&contentId=CH_4910_EP_407&audioContentId=CH_4910_EP_407
|
||||||
|
- strong [ref=e756]: "3회 - 셀주크 제국과 동로마의 첫 전투, 결과는? #만지케르트전투"
|
||||||
|
- generic [ref=e758]: 재생
|
||||||
|
- generic [ref=e759]:
|
||||||
|
- generic [ref=e760]:
|
||||||
|
- generic [ref=e761]:
|
||||||
|
- link "영어사전" [ref=e762] [cursor=pointer]:
|
||||||
|
- /url: https://en.dict.naver.com/#/mini/main
|
||||||
|
- link "It’s twelve." [ref=e763] [cursor=pointer]:
|
||||||
|
- /url: https://learn.dict.naver.com/m/endic/today/conversation.dict
|
||||||
|
- generic [ref=e765]: It’s twelve.
|
||||||
|
- link "단어 검색하기" [ref=e766] [cursor=pointer]:
|
||||||
|
- /url: https://en.dict.naver.com/#/mini/main
|
||||||
|
- link "papago 번역하기" [ref=e767] [cursor=pointer]:
|
||||||
|
- /url: https://papago.naver.com/?sk=ko&st=&tk=en
|
||||||
|
- generic [ref=e769]: papago
|
||||||
|
- generic [ref=e770]: 번역하기
|
||||||
|
- link "메모 로그인하기" [ref=e771] [cursor=pointer]:
|
||||||
|
- /url: https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/?to=widget
|
||||||
|
- generic [ref=e773]: 메모
|
||||||
|
- list [ref=e775]:
|
||||||
|
- listitem [ref=e776]
|
||||||
|
- listitem [ref=e777]
|
||||||
|
- listitem [ref=e778]:
|
||||||
|
- generic [ref=e779]: 로그인하기
|
||||||
|
- button "다음 페이지" [ref=e780] [cursor=pointer]:
|
||||||
|
- generic [ref=e781]: 다음 페이지
|
||||||
|
- link "모바일 네이버 메인 열기" [ref=e782] [cursor=pointer]:
|
||||||
|
- /url: https://m.naver.com/
|
||||||
|
- strong [ref=e783]: 모바일 네이버 메인
|
||||||
|
- text: 열기
|
||||||
|
- generic [ref=e786]:
|
||||||
|
- button "최상단으로 이동" [ref=e787] [cursor=pointer]:
|
||||||
|
- generic [ref=e788]: 최상단으로 이동
|
||||||
|
- button "홈 설정" [ref=e789] [cursor=pointer]:
|
||||||
|
- generic [ref=e790]: 홈 설정
|
||||||
|
- contentinfo [ref=e791]:
|
||||||
|
- generic [ref=e792]:
|
||||||
|
- generic [ref=e793]:
|
||||||
|
- iframe [ref=e796]:
|
||||||
|
- link "광고 이미지 광고 유니세프 한국위원회 의미 있는 4월 어린이를 지키는 약속의 증표 지금 유니세프 팀 팔찌 받기" [ref=f4e3] [cursor=pointer]:
|
||||||
|
- /url: https://siape.veta.naver.com/fxclick?eu=EU10043568&calp=-&oj=cQgn6aire5MOnC6WBYbmb9tirrR2H6fVusCYsE3LckHGk9JWj3yQyWx%2FhcG054wnCb5%2BPZ4dBW68ikgVu8ae7iGNcbrnFmKn&ac=9267155&src=8067405&br=4921545&evtcd=P901&x_ti=1529&tb=&oid=&sid1=&sid2=&rk=_SS_zRSpH1hCGftVVL7uaw&eltts=uuyZfa5b5lmB3qHjBRDDRQ%3D%3D&brs=Y&
|
||||||
|
- generic [ref=f4e4]:
|
||||||
|
- img "광고 이미지" [ref=f4e5]
|
||||||
|
- generic "광고" [ref=f4e6]
|
||||||
|
- generic [ref=f4e7]:
|
||||||
|
- strong [ref=f4e8]: 유니세프 한국위원회
|
||||||
|
- strong [ref=f4e9]: 의미 있는 4월
|
||||||
|
- generic [ref=f4e10]: 어린이를 지키는 약속의 증표
|
||||||
|
- generic [ref=f4e11]: 지금 유니세프 팀 팔찌 받기
|
||||||
|
- iframe [ref=e799]:
|
||||||
|
- link "광고 이미지 광고 초록우산 엄마 손 잡고 꼭 다시 걸을거야 재활의 고통보다 엄마의 눈물이 더 아픈 9살 지온이 돕기" [ref=f5e3] [cursor=pointer]:
|
||||||
|
- /url: https://siape.veta.naver.com/fxclick?eu=EU10043569&calp=-&oj=cQgn6aire5Nx8cfS51TDuttirrR2H6fVusCYsE3LckHGk9JWj3yQyWx%2FhcG054wnCb5%2BPZ4dBW68ikgVu8ae7iGNcbrnFmKn&ac=9265144&src=8060305&br=4918643&evtcd=P901&x_ti=1529&tb=&oid=&sid1=&sid2=&rk=x4HQP1PeLE33AwmjzutSRg&eltts=uuyZfa5b5lmB3qHjBRDDRQ%3D%3D&brs=Y&
|
||||||
|
- generic [ref=f5e4]:
|
||||||
|
- img "광고 이미지" [ref=f5e5]
|
||||||
|
- generic "광고" [ref=f5e6]
|
||||||
|
- generic [ref=f5e7]:
|
||||||
|
- strong [ref=f5e8]: 초록우산
|
||||||
|
- strong [ref=f5e9]: 엄마 손 잡고 꼭 다시 걸을거야
|
||||||
|
- generic [ref=f5e10]: 재활의 고통보다 엄마의 눈물이
|
||||||
|
- generic [ref=f5e11]: 더 아픈 9살 지온이 돕기
|
||||||
|
- iframe [ref=e802]:
|
||||||
|
- link "광고 이미지 문화체육관광부 수요일 문화혜택 알아보기 문화가 있는 날 확대 매주 수요일은 문화요일" [ref=f6e3] [cursor=pointer]:
|
||||||
|
- /url: https://siape.veta.naver.com/fxclick?eu=EU10043570&calp=-&oj=9gPJTdEI4gHf40n3ktJ9%2FNtirrR2H6fVusCYsE3LckHGk9JWj3yQyWx%2FhcG054wnCb5%2BPZ4dBW68ikgVu8ae7iGNcbrnFmKn&ac=9264215&src=8057129&br=4917350&evtcd=P901&x_ti=1507&tb=&oid=&sid1=&sid2=&rk=OvrvuDX6wBn974ijpia7Bg&eltts=uuyZfa5b5lmB3qHjBRDDRQ%3D%3D&brs=Y&
|
||||||
|
- img "광고 이미지" [ref=f6e5]
|
||||||
|
- generic [ref=f6e6]:
|
||||||
|
- strong [ref=f6e7]: 문화체육관광부
|
||||||
|
- strong [ref=f6e8]: 수요일 문화혜택 알아보기
|
||||||
|
- generic [ref=f6e9]: 문화가 있는 날 확대
|
||||||
|
- generic [ref=f6e10]: 매주 수요일은 문화요일
|
||||||
|
- generic [ref=e803]:
|
||||||
|
- heading "공지사항" [level=3] [ref=e805]:
|
||||||
|
- link "공지사항" [ref=e806] [cursor=pointer]:
|
||||||
|
- /url: https://www.naver.com/NOTICE
|
||||||
|
- link "서비스 전체보기" [ref=e807] [cursor=pointer]:
|
||||||
|
- /url: /more.html
|
||||||
|
- generic [ref=e808]:
|
||||||
|
- generic [ref=e809]:
|
||||||
|
- generic [ref=e810]:
|
||||||
|
- heading "Partners" [level=3] [ref=e811]
|
||||||
|
- link "네이버 임팩트" [ref=e812] [cursor=pointer]:
|
||||||
|
- /url: https://www.navercorp.com/esg/social
|
||||||
|
- link "네이버 비즈니스" [ref=e813] [cursor=pointer]:
|
||||||
|
- /url: https://business.naver.com/
|
||||||
|
- link "네이버 비즈니스 스쿨" [ref=e814] [cursor=pointer]:
|
||||||
|
- /url: https://bizschool.naver.com/
|
||||||
|
- link "네이버 광고 등록" [ref=e815] [cursor=pointer]:
|
||||||
|
- /url: https://ads.naver.com/
|
||||||
|
- link "스토어 개설" [ref=e816] [cursor=pointer]:
|
||||||
|
- /url: https://sell.storefarm.naver.com/#/home/about
|
||||||
|
- link "지역업체 등록" [ref=e817] [cursor=pointer]:
|
||||||
|
- /url: https://smartplace.naver.com/
|
||||||
|
- link "엑스퍼트 등록" [ref=e818] [cursor=pointer]:
|
||||||
|
- /url: https://expert.naver.com/expert/introduction?tab=guide#join
|
||||||
|
- generic [ref=e819]:
|
||||||
|
- heading "Developers" [level=3] [ref=e820]
|
||||||
|
- link "네이버 개발자 센터" [ref=e821] [cursor=pointer]:
|
||||||
|
- /url: https://developers.naver.com/
|
||||||
|
- link "오픈 API" [ref=e822] [cursor=pointer]:
|
||||||
|
- /url: https://developers.naver.com/docs/common/openapiguide/#/apilist.md
|
||||||
|
- link "오픈소스" [ref=e823] [cursor=pointer]:
|
||||||
|
- /url: https://naver.github.io/
|
||||||
|
- link "네이버 D2" [ref=e824] [cursor=pointer]:
|
||||||
|
- /url: https://d2.naver.com/
|
||||||
|
- link "네이버 D2SF" [ref=e825] [cursor=pointer]:
|
||||||
|
- /url: http://d2startup.com/
|
||||||
|
- link "네이버 랩스" [ref=e826] [cursor=pointer]:
|
||||||
|
- /url: https://www.naverlabs.com/
|
||||||
|
- generic [ref=e827]:
|
||||||
|
- generic [ref=e828]:
|
||||||
|
- link "웨일 브라우저" [ref=e829] [cursor=pointer]:
|
||||||
|
- /url: http://whale.naver.com/
|
||||||
|
- img "웨일 브라우저" [ref=e830]
|
||||||
|
- generic [ref=e831]:
|
||||||
|
- strong [ref=e832]: 웨일 브라우저
|
||||||
|
- link "이용안내" [ref=e833] [cursor=pointer]:
|
||||||
|
- /url: http://whale.naver.com/
|
||||||
|
- generic [ref=e834]:
|
||||||
|
- link "기업 사이트" [ref=e835] [cursor=pointer]:
|
||||||
|
- /url: https://www.navercorp.com
|
||||||
|
- img "기업 사이트" [ref=e836]
|
||||||
|
- generic [ref=e837]:
|
||||||
|
- strong [ref=e838]: 기업 사이트
|
||||||
|
- link "바로가기" [ref=e839] [cursor=pointer]:
|
||||||
|
- /url: https://www.navercorp.com
|
||||||
|
- generic [ref=e840]:
|
||||||
|
- heading "네이버 정책 및 약관" [level=3] [ref=e841]
|
||||||
|
- list [ref=e842]:
|
||||||
|
- listitem [ref=e843]:
|
||||||
|
- link "회사소개" [ref=e844] [cursor=pointer]:
|
||||||
|
- /url: https://www.navercorp.com/
|
||||||
|
- listitem [ref=e845]:
|
||||||
|
- link "인재채용" [ref=e846] [cursor=pointer]:
|
||||||
|
- /url: https://recruit.navercorp.com/
|
||||||
|
- listitem [ref=e847]:
|
||||||
|
- link "제휴제안" [ref=e848] [cursor=pointer]:
|
||||||
|
- /url: https://www.navercorp.com/company/partnership
|
||||||
|
- listitem [ref=e849]:
|
||||||
|
- link "이용약관" [ref=e850] [cursor=pointer]:
|
||||||
|
- /url: https://www.naver.com/policy/service.html
|
||||||
|
- listitem [ref=e851]:
|
||||||
|
- link "개인정보처리방침" [ref=e852] [cursor=pointer]:
|
||||||
|
- /url: https://www.naver.com/policy/privacy.html
|
||||||
|
- strong [ref=e853]: 개인정보처리방침
|
||||||
|
- listitem [ref=e854]:
|
||||||
|
- link "청소년보호정책" [ref=e855] [cursor=pointer]:
|
||||||
|
- /url: https://www.naver.com/policy/youthpolicy.html
|
||||||
|
- listitem [ref=e856]:
|
||||||
|
- link "네이버 정책" [ref=e857] [cursor=pointer]:
|
||||||
|
- /url: https://policy.naver.com/policy/service_group.html
|
||||||
|
- listitem [ref=e858]:
|
||||||
|
- link "고객센터" [ref=e859] [cursor=pointer]:
|
||||||
|
- /url: https://help.naver.com/
|
||||||
|
- link "ⓒ NAVER Corp." [ref=e861] [cursor=pointer]:
|
||||||
|
- /url: https://www.navercorp.com/
|
||||||
323
.playwright-cli/page-2026-04-09T15-44-37-420Z.yml
Normal file
323
.playwright-cli/page-2026-04-09T15-44-37-420Z.yml
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
- generic [active] [ref=e1]:
|
||||||
|
- generic [ref=e5]:
|
||||||
|
- link [ref=e6] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/mlp/web/package-landing?adType=DA&eventId=epz7WYtFAqoBj6JM
|
||||||
|
- link [ref=e7] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/mlp/web/package-landing?adType=DA&eventId=8k9NwjG8PpaAugUx
|
||||||
|
- generic [ref=e8]:
|
||||||
|
- generic [ref=e10]:
|
||||||
|
- list [ref=e11]:
|
||||||
|
- listitem [ref=e12]:
|
||||||
|
- link "판매자 가입" [ref=e13] [cursor=pointer]:
|
||||||
|
- /url: https://wing.coupang.com/tenants/vendor-signup/signup?utm_source=button_pc_coupang_app_category_3&utm_medium=non_paid&utm_id=onsite_ca&utm_content=20240328
|
||||||
|
- listitem [ref=e14]:
|
||||||
|
- link "고객센터" [ref=e15] [cursor=pointer]:
|
||||||
|
- /url: https://mc.coupang.com/ssr/desktop/contact/faq
|
||||||
|
- listitem [ref=e16]:
|
||||||
|
- link "회원가입" [ref=e17] [cursor=pointer]:
|
||||||
|
- /url: https://login.coupang.com/login/memberJoinFrm.pang
|
||||||
|
- listitem [ref=e18]:
|
||||||
|
- link "로그인" [ref=e19] [cursor=pointer]:
|
||||||
|
- /url: https://login.coupang.com/login/login.pang?rtnUrl=https%3A%2F%2Fwww.coupang.com%2Fnp%2Fpost%2Flogin%3Fr%3Dhttp%253A%252F%252Fwww.coupang.com%252F
|
||||||
|
- list [ref=e20]:
|
||||||
|
- listitem [ref=e21]: 즐겨찾기
|
||||||
|
- listitem [ref=e22]:
|
||||||
|
- generic [ref=e23] [cursor=pointer]: 입점신청
|
||||||
|
- generic [ref=e26]:
|
||||||
|
- generic [ref=e32] [cursor=pointer]: 카테고리
|
||||||
|
- generic [ref=e33]:
|
||||||
|
- generic [ref=e34]:
|
||||||
|
- link "Coupang" [ref=e35] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com
|
||||||
|
- img "Coupang" [ref=e36]
|
||||||
|
- generic [ref=e37]:
|
||||||
|
- link "전체" [ref=e40] [cursor=pointer]:
|
||||||
|
- /url: "#"
|
||||||
|
- textbox "쿠팡 상품 검색" [ref=e42]:
|
||||||
|
- /placeholder: 찾고 싶은 상품을 검색해보세요!
|
||||||
|
- button "검색" [ref=e44] [cursor=pointer]
|
||||||
|
- list [ref=e45]:
|
||||||
|
- listitem [ref=e46]:
|
||||||
|
- link "마이쿠팡" [ref=e47] [cursor=pointer]:
|
||||||
|
- /url: https://mc.coupang.com/ssr/desktop/order/list
|
||||||
|
- generic [ref=e48]: 마이쿠팡
|
||||||
|
- listitem [ref=e49]:
|
||||||
|
- link "0 장바구니" [ref=e50] [cursor=pointer]:
|
||||||
|
- /url: //cart.coupang.com/cartView.pang
|
||||||
|
- emphasis [ref=e51]: "0"
|
||||||
|
- generic [ref=e52]: 장바구니
|
||||||
|
- list [ref=e57]:
|
||||||
|
- listitem [ref=e58]:
|
||||||
|
- link "쿠팡플레이 쿠팡플레이" [ref=e59] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupangplay.com/catalog
|
||||||
|
- img "쿠팡플레이" [ref=e60]
|
||||||
|
- generic [ref=e61]: 쿠팡플레이
|
||||||
|
- listitem [ref=e62]:
|
||||||
|
- link "로켓배송 로켓배송" [ref=e63] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/campaigns/82
|
||||||
|
- img "로켓배송" [ref=e64]
|
||||||
|
- generic [ref=e65]: 로켓배송
|
||||||
|
- listitem [ref=e66]:
|
||||||
|
- link "로켓프레시 로켓프레시" [ref=e67] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/categories/393760
|
||||||
|
- img "로켓프레시" [ref=e68]
|
||||||
|
- generic [ref=e69]: 로켓프레시
|
||||||
|
- listitem [ref=e70]:
|
||||||
|
- link "다시 구매 다시 구매" [ref=e71] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/fbi?sourceType=home_section_fbi
|
||||||
|
- img "다시 구매" [ref=e72]
|
||||||
|
- generic [ref=e73]: 다시 구매
|
||||||
|
- listitem [ref=e75]:
|
||||||
|
- link "쿠팡비즈 쿠팡비즈" [ref=e76] [cursor=pointer]:
|
||||||
|
- /url: https://login.coupang.com/corporation/member/landing-page
|
||||||
|
- img "쿠팡비즈" [ref=e77]
|
||||||
|
- generic [ref=e78]: 쿠팡비즈
|
||||||
|
- listitem [ref=e79]:
|
||||||
|
- link "로켓직구 로켓직구" [ref=e80] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/coupangglobal
|
||||||
|
- img "로켓직구" [ref=e81]
|
||||||
|
- generic [ref=e82]: 로켓직구
|
||||||
|
- listitem [ref=e83]:
|
||||||
|
- link "골드박스 골드박스" [ref=e84] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/121237?sourceType=gm_crm_goldbox&subSourceType=gm_crm_gwsrtcut
|
||||||
|
- img "골드박스" [ref=e85]
|
||||||
|
- generic [ref=e86]: 골드박스
|
||||||
|
- listitem [ref=e87]:
|
||||||
|
- link "이달의신상 이달의신상" [ref=e88] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/136938
|
||||||
|
- img "이달의신상" [ref=e89]
|
||||||
|
- generic [ref=e90]: 이달의신상
|
||||||
|
- listitem [ref=e91]:
|
||||||
|
- link "판매자특가 판매자특가" [ref=e92] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/omp
|
||||||
|
- img "판매자특가" [ref=e93]
|
||||||
|
- generic [ref=e94]: 판매자특가
|
||||||
|
- listitem [ref=e95]:
|
||||||
|
- link "와우회원할인 와우회원할인" [ref=e96] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/campaigns/83
|
||||||
|
- img "와우회원할인" [ref=e97]
|
||||||
|
- generic [ref=e98]: 와우회원할인
|
||||||
|
- listitem [ref=e99]:
|
||||||
|
- link "이벤트/쿠폰 이벤트/쿠폰" [ref=e100] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/coupangbenefit
|
||||||
|
- img "이벤트/쿠폰" [ref=e101]
|
||||||
|
- generic [ref=e102]: 이벤트/쿠폰
|
||||||
|
- listitem [ref=e103]:
|
||||||
|
- link "반품마켓 반품마켓" [ref=e104] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/54908
|
||||||
|
- img "반품마켓" [ref=e105]
|
||||||
|
- generic [ref=e106]: 반품마켓
|
||||||
|
- listitem [ref=e107]:
|
||||||
|
- link "착한상점 착한상점" [ref=e108] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/63240
|
||||||
|
- img "착한상점" [ref=e109]
|
||||||
|
- generic [ref=e110]: 착한상점
|
||||||
|
- listitem [ref=e112]:
|
||||||
|
- link "기획전 기획전" [ref=e113] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/bep?sourceType=gm_crm_oms&subSourceType=gm_crm_gwsrtcut
|
||||||
|
- img "기획전" [ref=e114]
|
||||||
|
- generic [ref=e115]: 기획전
|
||||||
|
- listitem [ref=e116]:
|
||||||
|
- link "쿠팡트래블 쿠팡트래블" [ref=e117] [cursor=pointer]:
|
||||||
|
- /url: https://trip.coupang.com/?channel=gnb
|
||||||
|
- img "쿠팡트래블" [ref=e118]
|
||||||
|
- generic [ref=e119]: 쿠팡트래블
|
||||||
|
- listitem [ref=e121]:
|
||||||
|
- link "입점신청 입점신청" [ref=e122] [cursor=pointer]:
|
||||||
|
- /url: https://wing.coupang.com/tenants/vendor-signup/signup?utm_source=button_pc_coupang_shortcut_1&utm_medium=non_paid&utm_id=onsite_ca&utm_content=202411
|
||||||
|
- img "입점신청" [ref=e123]
|
||||||
|
- generic [ref=e124]: 입점신청
|
||||||
|
- article [ref=e127]:
|
||||||
|
- list [ref=e128]:
|
||||||
|
- listitem [ref=e129]:
|
||||||
|
- link [ref=e130] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/kd1961/487606?source=brandstore_display_ads&adType=DA&eventId=lsKDUCgcKEKkjiRL
|
||||||
|
- listitem [ref=e131]:
|
||||||
|
- link [ref=e132] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/woongjinfoods/486609?source=brandstore_display_ads&adType=DA&eventId=BfiMXhBlUxpCwPAx
|
||||||
|
- listitem [ref=e133]:
|
||||||
|
- link [ref=e134] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/campaigns/1440
|
||||||
|
- listitem [ref=e135]:
|
||||||
|
- link [ref=e136] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/78273
|
||||||
|
- listitem [ref=e137]:
|
||||||
|
- link [ref=e138] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/164807
|
||||||
|
- listitem [ref=e139]:
|
||||||
|
- link [ref=e140] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/68594
|
||||||
|
- listitem [ref=e141]:
|
||||||
|
- link [ref=e142] [cursor=pointer]:
|
||||||
|
- /url: https://wing.coupang.com/tenants/vendor-signup/signup?utm_source=button_pc_coupang_web_rignt_wing&utm_medium=non_paid&utm_id=onsite_ca&utm_content=20240516
|
||||||
|
- generic:
|
||||||
|
- link "장바구니 0" [ref=e144] [cursor=pointer]:
|
||||||
|
- /url: //cart.coupang.com/cartView.pang
|
||||||
|
- generic [ref=e145]: 장바구니
|
||||||
|
- emphasis [ref=e146]: "0"
|
||||||
|
- generic [ref=e147]:
|
||||||
|
- generic [ref=e148]: 최근본상품
|
||||||
|
- emphasis [ref=e149]: "0"
|
||||||
|
- generic [ref=e150]:
|
||||||
|
- list [ref=e151]
|
||||||
|
- paragraph [ref=e152]:
|
||||||
|
- generic [ref=e153]:
|
||||||
|
- strong
|
||||||
|
- text: /
|
||||||
|
- emphasis
|
||||||
|
- generic [ref=e154]:
|
||||||
|
- link "prev" [ref=e155] [cursor=pointer]:
|
||||||
|
- /url: 이전 페이지 보기
|
||||||
|
- link "next" [ref=e156] [cursor=pointer]:
|
||||||
|
- /url: 다음 페이지 보기
|
||||||
|
- generic [ref=e157]:
|
||||||
|
- generic [ref=e160]:
|
||||||
|
- link [ref=e162] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/A01064449/516623?source=brandstore_display_ads&adType=DA&eventId=0ygW7mjzNMRAMElJ&from=home_C1&traid=home_C1&trcid=11703333
|
||||||
|
- list [ref=e163]:
|
||||||
|
- listitem [ref=e165]:
|
||||||
|
- link [ref=e166] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/A01064449/516623?source=brandstore_display_ads&adType=DA&eventId=0ygW7mjzNMRAMElJ&from=home_C1&traid=home_C1&trcid=11703333
|
||||||
|
- img [ref=e167]
|
||||||
|
- listitem [ref=e170]:
|
||||||
|
- link [ref=e171] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/kleannara/349132?source=brandstore_display_ads&adType=DA&eventId=SH5kfQHMCDwQae4s&from=home_C1&traid=home_C1&trcid=11702264
|
||||||
|
- img [ref=e172]
|
||||||
|
- listitem [ref=e175]:
|
||||||
|
- link [ref=e176] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/A00003619/490614?source=brandstore_display_ads&adType=DA&eventId=fQORb49JQ40ui4l3&from=home_C1&traid=home_C1&trcid=11700357
|
||||||
|
- img [ref=e177]
|
||||||
|
- listitem [ref=e180]:
|
||||||
|
- link [ref=e181] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/166727?subSourceType=gm_crm_gwc1mainbnr_p2981_b1004606_c533502&sourceType=gm_crm_oms&from=home_C1&traid=home_C1&trcid=812431103159
|
||||||
|
- img [ref=e182]
|
||||||
|
- listitem [ref=e185]:
|
||||||
|
- link [ref=e186] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/mlp/web/package-landing?from=home_C1&traid=home_C1&trcid=812431073637
|
||||||
|
- img [ref=e187]
|
||||||
|
- listitem [ref=e190]:
|
||||||
|
- link [ref=e191] [cursor=pointer]:
|
||||||
|
- /url: https://login.coupang.com/login/login.pang?rtnUrl=https%3A%2Fmc.coupang.com%2Fssr&from=home_C1&traid=home_C1&trcid=812431097407
|
||||||
|
- img [ref=e192]
|
||||||
|
- generic [ref=e195]:
|
||||||
|
- generic [ref=e196]:
|
||||||
|
- generic [ref=e197]:
|
||||||
|
- heading "오늘의 발견" [level=2] [ref=e198]
|
||||||
|
- heading "오늘 쿠팡이 엄선한 가장 HOT한 상품!" [level=3] [ref=e199]
|
||||||
|
- list [ref=e201]:
|
||||||
|
- listitem [ref=e202]:
|
||||||
|
- link [ref=e203] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/pigeonofficial/280389?source=brandstore_display_ads&adType=DA&eventId=LxgeOlP2rAdYqvnp&from=home_C2&traid=home_C2&trcid=11701308
|
||||||
|
- img [ref=e206]
|
||||||
|
- listitem [ref=e209]:
|
||||||
|
- link [ref=e210] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/ottogi/301273?source=brandstore_display_ads&adType=DA&eventId=hRdXj1hrn9lhzPBM&from=home_C2&traid=home_C2&trcid=11697862
|
||||||
|
- img [ref=e213]
|
||||||
|
- listitem [ref=e216]:
|
||||||
|
- link [ref=e217] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/167853?adType=DA&eventId=7utXaPV38Kqx6PIo&from=home_C2&traid=home_C2&trcid=11702945
|
||||||
|
- img [ref=e220]
|
||||||
|
- listitem [ref=e223]:
|
||||||
|
- link [ref=e224] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/missha/490691?source=brandstore_display_ads&adType=DA&eventId=a2fA4jgINBu1UGz0&from=home_C2&traid=home_C2&trcid=11700243
|
||||||
|
- img [ref=e227]
|
||||||
|
- listitem [ref=e230]:
|
||||||
|
- link [ref=e231] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/magicwrap/480423?source=brandstore_display_ads&adType=DA&eventId=nohHc8dlSu2e3XBP&from=home_C2&traid=home_C2&trcid=11704115
|
||||||
|
- img [ref=e234]
|
||||||
|
- listitem [ref=e237]:
|
||||||
|
- link [ref=e238] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/167919?adType=DA&eventId=Yv35b3fCpbVgECkq&from=home_C2&traid=home_C2&trcid=11703217
|
||||||
|
- img [ref=e241]
|
||||||
|
- listitem [ref=e244]:
|
||||||
|
- link [ref=e245] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/srise/425294?source=brandstore_display_ads&adType=DA&eventId=dlhxjV4iS5ZKCgt6&from=home_C2&traid=home_C2&trcid=11700789
|
||||||
|
- img [ref=e248]
|
||||||
|
- listitem [ref=e251]:
|
||||||
|
- link [ref=e252] [cursor=pointer]:
|
||||||
|
- /url: https://pages.coupang.com/p/167989?adType=DA&eventId=K3naQUtxIEtfh9tb&from=home_C2&traid=home_C2&trcid=11703604
|
||||||
|
- img [ref=e255]
|
||||||
|
- listitem [ref=e258]:
|
||||||
|
- link "코멧(로고) 어린이용 일회용 장갑" [ref=e259] [cursor=pointer]:
|
||||||
|
- /url: /vp/products/7225189423?itemId=18319675609&vendorItemId=80324048129&from=home_C2&traid=home_C2&trcid=4750546
|
||||||
|
- img "코멧(로고) 어린이용 일회용 장갑" [ref=e260]
|
||||||
|
- img [ref=e263]
|
||||||
|
- link [ref=e270] [cursor=pointer]:
|
||||||
|
- /url: https://shop.coupang.com/cj/418171?source=brandstore_display_ads&adType=DA&eventId=fYJZfC1m0fEwKJas&from=home_event_banner&traid=home_event_banner
|
||||||
|
- paragraph [ref=e273]: Loading...
|
||||||
|
- contentinfo [ref=e274]:
|
||||||
|
- generic [ref=e275]:
|
||||||
|
- generic [ref=e276]:
|
||||||
|
- link "회사소개" [ref=e277] [cursor=pointer]:
|
||||||
|
- /url: https://news.coupang.com/
|
||||||
|
- link "Investor Relations" [ref=e278] [cursor=pointer]:
|
||||||
|
- /url: https://ir.aboutcoupang.com/overview/default.aspx
|
||||||
|
- link "인재채용" [ref=e279] [cursor=pointer]:
|
||||||
|
- /url: https://rocketyourcareer.kr.coupang.com
|
||||||
|
- link "입점/제휴문의" [ref=e280] [cursor=pointer]:
|
||||||
|
- /url: https://marketplace.coupangcorp.com/s/?utm_source=button_pc&utm_medium=non_paid&utm_campaign=onsite_ca&utm_id=coupang_app?inflow=WEB_FOOTER_B
|
||||||
|
- link "공지사항" [ref=e281] [cursor=pointer]:
|
||||||
|
- /url: https://mc.coupang.com/ssr/desktop/contact/notice
|
||||||
|
- link "고객의 소리" [ref=e282] [cursor=pointer]:
|
||||||
|
- /url: https://mc.coupang.com/ssr/desktop/contact/voc
|
||||||
|
- link "이용약관" [ref=e283] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/policies/terms
|
||||||
|
- link "개인정보 처리방침" [ref=e284] [cursor=pointer]:
|
||||||
|
- /url: https://privacy.coupang.com/ko/center/coupang
|
||||||
|
- strong [ref=e285]: 개인정보 처리방침
|
||||||
|
- link "정보보호/개인정보보호 인증" [ref=e286] [cursor=pointer]:
|
||||||
|
- /url: https://privacy.coupang.com/ko/security/status
|
||||||
|
- link "쿠팡페이 이용약관" [ref=e287] [cursor=pointer]:
|
||||||
|
- /url: https://rocketpay.coupang.com/rocketpay/operationTerms/coupangPcFooter
|
||||||
|
- link "신뢰관리센터" [ref=e288] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/safety
|
||||||
|
- link "제휴마케팅" [ref=e289] [cursor=pointer]:
|
||||||
|
- /url: https://partners.coupang.com/
|
||||||
|
- link "광고안내" [ref=e290] [cursor=pointer]:
|
||||||
|
- /url: https://ads.coupang.com
|
||||||
|
- paragraph [ref=e294] [cursor=pointer]: Global Site
|
||||||
|
- generic [ref=e296]:
|
||||||
|
- generic [ref=e297]:
|
||||||
|
- link "COUPANG" [ref=e298] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/
|
||||||
|
- generic [ref=e299]:
|
||||||
|
- text: "상호명 및 호스팅 서비스 제공 : 쿠팡(주)"
|
||||||
|
- text: "대표이사 : 로저스 해롤드 린(Rogers Harold Lynn)"
|
||||||
|
- text: 서울시 송파구 송파대로 570
|
||||||
|
- text: "사업자 등록번호 : 120-88-00767"
|
||||||
|
- text: "통신판매업신고 : 2017-서울송파-0680"
|
||||||
|
- link "사업자정보 확인 >" [ref=e300] [cursor=pointer]:
|
||||||
|
- /url: http://www.ftc.go.kr/info/bizinfo/communicationViewPopup.jsp?wrkr_no=1208800767
|
||||||
|
- 'link "365고객센터 | 전자금융거래분쟁처리담당 1577-7011 (유료) 서울시 송파구 송파대로 570 email : help@coupang.com" [ref=e302] [cursor=pointer]':
|
||||||
|
- /url: https://mc.coupang.com/ssr/desktop/contact/inquiry
|
||||||
|
- strong [ref=e303]: 365고객센터
|
||||||
|
- text: "| 전자금융거래분쟁처리담당"
|
||||||
|
- emphasis [ref=e304]: 1577-7011 (유료)
|
||||||
|
- text: 서울시 송파구 송파대로 570
|
||||||
|
- text: "email : help@coupang.com"
|
||||||
|
- paragraph [ref=e305]:
|
||||||
|
- strong [ref=e306]: 채무지급보증 안내
|
||||||
|
- generic [ref=e307]:
|
||||||
|
- text: 당사는 고객님이 현금 결제한 금액에 대해
|
||||||
|
- text: 채무지급보증 계약을 체결하여
|
||||||
|
- text: 안전거래를 보장하고 있습니다.
|
||||||
|
- link "서비스 가입사실 확인 >" [ref=e308] [cursor=pointer]:
|
||||||
|
- /url: https://www.coupang.com/np/etc/popWooriService
|
||||||
|
- generic [ref=e314]:
|
||||||
|
- paragraph [ref=e315]:
|
||||||
|
- text: 사이버몰 내 판매되는 상품 중에는 쿠팡에 등록한 개별 판매자가 판매하는 마켓플레이스(오픈마켓) 상품이 포함되어 있습니다.
|
||||||
|
- text: 마켓플레이스(오픈마켓) 상품의 경우 쿠팡은 통신판매중개자이며 통신판매의 당사자가 아닙니다.
|
||||||
|
- text: 쿠팡은 마켓플레이스(오픈마켓) 상품, 거래정보 및 거래 등에 대하여 책임을 지지 않습니다.
|
||||||
|
- text: 쿠팡은 소비자 보호와 안전거래를 위해 신뢰관리센터(CM112@coupang.com)를 운영하고 있으며, 관련 분쟁이 발생할 경우 별도의 분쟁 처리절차에 의거 분쟁이 처리됩니다.
|
||||||
|
- text: Copyright © Coupang Corp. 2010-2025 All Rights Reserved.
|
||||||
|
- list [ref=e316]:
|
||||||
|
- listitem [ref=e317]:
|
||||||
|
- link [ref=e318] [cursor=pointer]:
|
||||||
|
- /url: https://www.facebook.com/Coupang.korea
|
||||||
|
- listitem [ref=e319]:
|
||||||
|
- link [ref=e320] [cursor=pointer]:
|
||||||
|
- /url: https://news.coupang.com/
|
||||||
|
- listitem [ref=e321]:
|
||||||
|
- link [ref=e322] [cursor=pointer]:
|
||||||
|
- /url: https://www.instagram.com/coupang
|
||||||
|
- alert [ref=e323]
|
||||||
30
.playwright-cli/page-2026-04-09T15-46-04-997Z.yml
Normal file
30
.playwright-cli/page-2026-04-09T15-46-04-997Z.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
- generic [ref=e4]:
|
||||||
|
- generic [ref=e6]: HYUN
|
||||||
|
- table [ref=e8]:
|
||||||
|
- rowgroup [ref=e13]:
|
||||||
|
- row "ID 로그인" [ref=e14]:
|
||||||
|
- rowheader "ID" [ref=e15]
|
||||||
|
- cell [ref=e16]:
|
||||||
|
- textbox [active] [ref=e17]
|
||||||
|
- cell "로그인" [ref=e18]:
|
||||||
|
- button "로그인" [ref=e19] [cursor=pointer]
|
||||||
|
- row "PW" [ref=e21]:
|
||||||
|
- rowheader "PW" [ref=e22]
|
||||||
|
- cell [ref=e23]:
|
||||||
|
- textbox [ref=e24]
|
||||||
|
- row "아이디저장" [ref=e25]:
|
||||||
|
- cell [ref=e26]
|
||||||
|
- cell "아이디저장" [ref=e27]:
|
||||||
|
- generic [ref=e28]:
|
||||||
|
- checkbox "아이디저장" [ref=e29]
|
||||||
|
- text: 아이디저장
|
||||||
|
- cell [ref=e30]
|
||||||
|
- generic [ref=e32]:
|
||||||
|
- text: "접속 IP : 114.205.211.211"
|
||||||
|
- text: "접속 웹브라우저 : 크롬(Chrome)"
|
||||||
|
- link [ref=e35] [cursor=pointer]:
|
||||||
|
- /url: //www.bizmax.net
|
||||||
|
- img [ref=e36]
|
||||||
|
- link "비즈맥스솔루션 BIZMAX.NET" [ref=e39] [cursor=pointer]:
|
||||||
|
- /url: //www.bizmax.net
|
||||||
|
- generic [ref=e40]: 전산 프로그램 개설 문의 ☏ 010-2522-9862
|
||||||
34
.playwright-cli/page-2026-04-09T15-46-23-620Z.yml
Normal file
34
.playwright-cli/page-2026-04-09T15-46-23-620Z.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
- generic [ref=e1]:
|
||||||
|
- generic [ref=e4]:
|
||||||
|
- generic [ref=e6]: HYUN
|
||||||
|
- table [ref=e8]:
|
||||||
|
- rowgroup [ref=e13]:
|
||||||
|
- row "ID JH_1204 로그인" [ref=e41]:
|
||||||
|
- rowheader "ID" [ref=e15]
|
||||||
|
- cell "JH_1204" [ref=e42]:
|
||||||
|
- textbox [ref=e17]: JH_1204
|
||||||
|
- cell "로그인" [ref=e18]:
|
||||||
|
- button "로그인" [active] [ref=e19] [cursor=pointer]
|
||||||
|
- row "PW 12345" [ref=e43]:
|
||||||
|
- rowheader "PW" [ref=e22]
|
||||||
|
- cell "12345" [ref=e44]:
|
||||||
|
- textbox [ref=e24]: "12345"
|
||||||
|
- row "아이디저장" [ref=e25]:
|
||||||
|
- cell [ref=e26]
|
||||||
|
- cell "아이디저장" [ref=e27]:
|
||||||
|
- generic [ref=e28]:
|
||||||
|
- checkbox "아이디저장" [ref=e29]
|
||||||
|
- text: 아이디저장
|
||||||
|
- cell [ref=e30]
|
||||||
|
- generic [ref=e32]:
|
||||||
|
- text: "접속 IP : 114.205.211.211"
|
||||||
|
- text: "접속 웹브라우저 : 크롬(Chrome)"
|
||||||
|
- link [ref=e35] [cursor=pointer]:
|
||||||
|
- /url: //www.bizmax.net
|
||||||
|
- img [ref=e36]
|
||||||
|
- link "비즈맥스솔루션 BIZMAX.NET" [ref=e39] [cursor=pointer]:
|
||||||
|
- /url: //www.bizmax.net
|
||||||
|
- generic [ref=e40]: 전산 프로그램 개설 문의 ☏ 010-2522-9862
|
||||||
|
- generic [ref=e45]:
|
||||||
|
- button "×" [ref=e46] [cursor=pointer]
|
||||||
|
- generic [ref=e47]: 아이디 또는 비밀번호를 다시 확인하세요.
|
||||||
1324
.playwright-cli/page-2026-04-09T15-47-46-538Z.yml
Normal file
1324
.playwright-cli/page-2026-04-09T15-47-46-538Z.yml
Normal file
File diff suppressed because it is too large
Load Diff
30
.playwright-cli/page-2026-04-09T15-52-10-730Z.yml
Normal file
30
.playwright-cli/page-2026-04-09T15-52-10-730Z.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
- generic [ref=e4]:
|
||||||
|
- generic [ref=e6]: HYUN
|
||||||
|
- table [ref=e8]:
|
||||||
|
- rowgroup [ref=e13]:
|
||||||
|
- row "ID 로그인" [ref=e14]:
|
||||||
|
- rowheader "ID" [ref=e15]
|
||||||
|
- cell [ref=e16]:
|
||||||
|
- textbox [active] [ref=e17]
|
||||||
|
- cell "로그인" [ref=e18]:
|
||||||
|
- button "로그인" [ref=e19] [cursor=pointer]
|
||||||
|
- row "PW" [ref=e21]:
|
||||||
|
- rowheader "PW" [ref=e22]
|
||||||
|
- cell [ref=e23]:
|
||||||
|
- textbox [ref=e24]
|
||||||
|
- row "아이디저장" [ref=e25]:
|
||||||
|
- cell [ref=e26]
|
||||||
|
- cell "아이디저장" [ref=e27]:
|
||||||
|
- generic [ref=e28]:
|
||||||
|
- checkbox "아이디저장" [ref=e29]
|
||||||
|
- text: 아이디저장
|
||||||
|
- cell [ref=e30]
|
||||||
|
- generic [ref=e32]:
|
||||||
|
- text: "접속 IP : 114.205.211.211"
|
||||||
|
- text: "접속 웹브라우저 : 크롬(Chrome)"
|
||||||
|
- link [ref=e35] [cursor=pointer]:
|
||||||
|
- /url: //www.bizmax.net
|
||||||
|
- img [ref=e36]
|
||||||
|
- link "비즈맥스솔루션 BIZMAX.NET" [ref=e39] [cursor=pointer]:
|
||||||
|
- /url: //www.bizmax.net
|
||||||
|
- generic [ref=e40]: 전산 프로그램 개설 문의 ☏ 010-2522-9862
|
||||||
BIN
.playwright-cli/현대생활건강-프로그램-고객목록-2026-04-10.xlsx
Normal file
BIN
.playwright-cli/현대생활건강-프로그램-고객목록-2026-04-10.xlsx
Normal file
Binary file not shown.
200
README-bizmax.md
Normal file
200
README-bizmax.md
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# Bizmax Excel Downloader
|
||||||
|
|
||||||
|
이 디렉터리에는 `hyun.bizmax.net`, `hyun2.bizmax.net` 고객목록 엑셀을 기간별로 다운로드하는 스크립트가 들어 있습니다.
|
||||||
|
|
||||||
|
## 파일
|
||||||
|
|
||||||
|
- `bizmax-download-excel.ts`: 실제 다운로드 로직
|
||||||
|
- `convert-xlsx-to-csv.ts`: 다운로드된 `.xlsx` 전체를 하나의 `.csv`로 합침
|
||||||
|
- `compare-csv-phone.ts`: `a.csv`, `b.csv`를 전화번호 기준으로 비교
|
||||||
|
- `run-bizmax.sh`: `hyun`, `hyun2`, `all` 선택 실행
|
||||||
|
- `run-hyun.sh`: `hyun.bizmax.net` 전용 실행
|
||||||
|
- `run-hyun2.sh`: `hyun2.bizmax.net` 전용 실행
|
||||||
|
- `run-convert-csv.sh`: 다운로드된 `.xlsx` 전체를 하나의 `.csv`로 합침
|
||||||
|
- `run-compare-csv.sh`: `a.csv`, `b.csv`를 전화번호 기준으로 비교
|
||||||
|
- `.env.example`: 환경변수 예시
|
||||||
|
|
||||||
|
## 1. 환경 설정
|
||||||
|
|
||||||
|
`.env.example`를 복사해서 `.env` 파일을 만듭니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
`.env` 예시:
|
||||||
|
|
||||||
|
```env
|
||||||
|
BIZMAX_ID=JH1204
|
||||||
|
BIZMAX_PASSWORD=12345
|
||||||
|
BIZMAX_RANGE_START=2016-01-01
|
||||||
|
BIZMAX_BATCH_MONTHS=3
|
||||||
|
BIZMAX_BASE_URLS=https://hyun.bizmax.net,https://hyun2.bizmax.net
|
||||||
|
BIZMAX_OUTPUT_DIR=/home/pure13700/project/download/output
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 의존성 설치
|
||||||
|
|
||||||
|
최초 1회:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
현재 `package.json`에는 `axios`, `cheerio`, `xlsx`가 들어 있습니다.
|
||||||
|
|
||||||
|
## 3. 실행 방법
|
||||||
|
|
||||||
|
두 사이트 모두 실행:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run-bizmax.sh all
|
||||||
|
```
|
||||||
|
|
||||||
|
`hyun.bizmax.net`만 실행:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run-bizmax.sh hyun
|
||||||
|
```
|
||||||
|
|
||||||
|
또는:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run-hyun.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
`hyun2.bizmax.net`만 실행:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run-bizmax.sh hyun2
|
||||||
|
```
|
||||||
|
|
||||||
|
또는:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run-hyun2.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
직접 TypeScript 파일 실행:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node --experimental-strip-types ./bizmax-download-excel.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
이 경우 `.env`는 자동 로드되지 않으므로, 셸에서 환경변수를 먼저 export 하거나 `run-*.sh` 사용을 권장합니다.
|
||||||
|
|
||||||
|
## 4. 동작 방식
|
||||||
|
|
||||||
|
- 로그인
|
||||||
|
- 고객목록 진입
|
||||||
|
- `2016-01-01`부터 현재 날짜까지 3개월 단위로 조회
|
||||||
|
- 각 기간별 조회 결과가 `0건`이면 건너뜀
|
||||||
|
- `1건 이상`이면 첫 번째 엑셀 다운로드
|
||||||
|
- 파일명에 사이트명과 기간을 붙여 저장
|
||||||
|
|
||||||
|
예시 출력:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[hyun_bizmax_net] SKIP 2016-01-01~2016-03-31 (0건)
|
||||||
|
/home/pure13700/project/download/output/hyun_bizmax_net_현대생활건강_프로그램_고객목록_2016-04-01_2016-06-30.xlsx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. 저장 위치
|
||||||
|
|
||||||
|
기본 저장 위치:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/home/pure13700/project/download/output
|
||||||
|
```
|
||||||
|
|
||||||
|
변경하려면 `.env`의 `BIZMAX_OUTPUT_DIR` 값을 수정합니다.
|
||||||
|
|
||||||
|
CSV 저장 위치 기본값:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/home/pure13700/project/download/output/csv
|
||||||
|
```
|
||||||
|
|
||||||
|
변경하려면 환경변수 `BIZMAX_CSV_DIR`를 사용합니다.
|
||||||
|
|
||||||
|
## 6. XLSX -> CSV 변환
|
||||||
|
|
||||||
|
다운로드된 전체 `.xlsx`를 하나의 `.csv`로 합치기:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run-convert-csv.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
또는:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node --experimental-strip-types ./convert-xlsx-to-csv.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
다른 CSV 출력 폴더를 쓰려면:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
BIZMAX_CSV_DIR=/home/pure13700/project/download/output/csv node --experimental-strip-types ./convert-xlsx-to-csv.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
기본 출력 파일:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/home/pure13700/project/download/output/csv/bizmax-all.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
파일명을 바꾸려면:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
BIZMAX_CSV_NAME=my-all.csv node --experimental-strip-types ./convert-xlsx-to-csv.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
동작 방식:
|
||||||
|
|
||||||
|
- `output/` 아래의 `.xlsx` 파일들을 찾음
|
||||||
|
- 각 워크시트를 읽음
|
||||||
|
- 모든 데이터를 하나의 CSV로 합침
|
||||||
|
- 앞에 `source_file`, `source_sheet` 컬럼을 추가함
|
||||||
|
|
||||||
|
참고:
|
||||||
|
|
||||||
|
- `.xlsx` 파싱은 `xlsx` 패키지로 처리합니다.
|
||||||
|
- 모든 파일의 헤더 구조가 동일하다는 전제를 두는 편이 안전합니다.
|
||||||
|
|
||||||
|
## 7. 주의 사항
|
||||||
|
|
||||||
|
- 계정이 SMS 추가 인증을 요구하면 `axios`만으로는 완료되지 않습니다.
|
||||||
|
- 사이트 구조가 바뀌면 hidden input 이름이나 다운로드 파라미터도 같이 바뀔 수 있습니다.
|
||||||
|
- 장기간 전체 다운로드라 실행 시간이 꽤 걸릴 수 있습니다.
|
||||||
|
|
||||||
|
## 8. CSV 전화번호 비교
|
||||||
|
|
||||||
|
기본 실행:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
COMPARE_FILE_A=./a.csv COMPARE_FILE_B=./b.csv ./run-compare-csv.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
또는:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
COMPARE_FILE_A=./a.csv COMPARE_FILE_B=./b.csv node --experimental-strip-types ./compare-csv-phone.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
기본값:
|
||||||
|
|
||||||
|
- `COMPARE_MODE=intersection`: `a.csv`와 `b.csv`에 모두 있는 전화번호만 출력
|
||||||
|
- `COMPARE_PHONE_COL_A=phone`
|
||||||
|
- `COMPARE_PHONE_COL_B=phone`
|
||||||
|
|
||||||
|
`a.csv`에만 있는 전화번호만 뽑으려면:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
COMPARE_FILE_A=./a.csv COMPARE_FILE_B=./b.csv COMPARE_MODE=only_a node --experimental-strip-types ./compare-csv-phone.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 파일 기본값:
|
||||||
|
|
||||||
|
```text
|
||||||
|
./compare-intersection.csv
|
||||||
|
```
|
||||||
BIN
__pycache__/convert-xlsx-to-csv.cpython-314.pyc
Normal file
BIN
__pycache__/convert-xlsx-to-csv.cpython-314.pyc
Normal file
Binary file not shown.
451
bizmax-download-excel.ts
Normal file
451
bizmax-download-excel.ts
Normal file
@@ -0,0 +1,451 @@
|
|||||||
|
import axios, {
|
||||||
|
type AxiosRequestConfig,
|
||||||
|
type AxiosResponse,
|
||||||
|
type RawAxiosResponseHeaders,
|
||||||
|
} from "axios";
|
||||||
|
import * as cheerio from "cheerio";
|
||||||
|
import { createHash } from "node:crypto";
|
||||||
|
import { mkdir, writeFile } from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const DEFAULT_BASE_URLS = ["https://hyun.bizmax.net", "https://hyun2.bizmax.net"];
|
||||||
|
const BASE_URLS = (
|
||||||
|
process.env.BIZMAX_BASE_URLS ??
|
||||||
|
process.env.BIZMAX_BASE_URL ??
|
||||||
|
DEFAULT_BASE_URLS.join(",")
|
||||||
|
)
|
||||||
|
.split(",")
|
||||||
|
.map((value) => value.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
const LOGIN_ID = process.env.BIZMAX_ID;
|
||||||
|
const LOGIN_PASSWORD = process.env.BIZMAX_PASSWORD;
|
||||||
|
const OUTPUT_DIR = process.env.BIZMAX_OUTPUT_DIR ?? path.resolve(process.cwd(), "output");
|
||||||
|
const CUSTOMER_LIST_PATH = "/customer/tpl/customer_list.php";
|
||||||
|
const RANGE_START = process.env.BIZMAX_RANGE_START ?? "2016-01-01";
|
||||||
|
const BATCH_MONTHS = Number(process.env.BIZMAX_BATCH_MONTHS ?? "3");
|
||||||
|
|
||||||
|
type LoginResponse = {
|
||||||
|
ret_code?: number;
|
||||||
|
ret_msg?: string;
|
||||||
|
login_succ?: string | number;
|
||||||
|
u_sms_a?: string;
|
||||||
|
f_url?: string;
|
||||||
|
lt?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SimpleCookieJar {
|
||||||
|
private readonly cookies = new Map<string, string>();
|
||||||
|
|
||||||
|
addFromHeaders(setCookie: string[] = []): void {
|
||||||
|
for (const cookieLine of setCookie) {
|
||||||
|
const [pair] = cookieLine.split(";", 1);
|
||||||
|
if (!pair) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eqIndex = pair.indexOf("=");
|
||||||
|
if (eqIndex <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = pair.slice(0, eqIndex).trim();
|
||||||
|
const value = pair.slice(eqIndex + 1).trim();
|
||||||
|
this.cookies.set(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toHeader(): string {
|
||||||
|
return Array.from(this.cookies.entries())
|
||||||
|
.map(([name, value]) => `${name}=${value}`)
|
||||||
|
.join("; ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function md5(value: string): string {
|
||||||
|
return createHash("md5").update(value).digest("hex");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRequiredEnv(name: string, value: string | undefined): string {
|
||||||
|
if (!value) {
|
||||||
|
throw new Error(`Missing required environment variable: ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSetCookieHeaders(headers: RawAxiosResponseHeaders | Record<string, unknown>): string[] {
|
||||||
|
const headerValue = headers["set-cookie"];
|
||||||
|
if (Array.isArray(headerValue)) {
|
||||||
|
return headerValue.filter((item): item is string => typeof item === "string");
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function request<T = unknown>(
|
||||||
|
jar: SimpleCookieJar,
|
||||||
|
config: AxiosRequestConfig,
|
||||||
|
): Promise<AxiosResponse<T>> {
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
||||||
|
...(config.headers as Record<string, string> | undefined),
|
||||||
|
};
|
||||||
|
|
||||||
|
const cookieHeader = jar.toHeader();
|
||||||
|
if (cookieHeader) {
|
||||||
|
headers.Cookie = cookieHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios<T>({
|
||||||
|
...config,
|
||||||
|
headers,
|
||||||
|
validateStatus: () => true,
|
||||||
|
maxRedirects: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
jar.addFromHeaders(getSetCookieHeaders(response.headers));
|
||||||
|
|
||||||
|
if (response.status >= 400) {
|
||||||
|
throw new Error(`Request failed: ${config.method ?? "GET"} ${config.url} -> ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
function absoluteUrl(baseUrl: string, urlOrPath: string): string {
|
||||||
|
return new URL(urlOrPath, baseUrl).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseLoginPage(html: string): { appName: string; authStep: string } {
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
const appName = $('input[name="app_name"]').val()?.toString() ?? "Chrome";
|
||||||
|
const authStep = $('input[name="auth_step"]').val()?.toString() ?? "1";
|
||||||
|
return { appName, authStep };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseExcelForm(html: string): { action: string; fields: Record<string, string> } {
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
const form = $('form[name="excel_form"]');
|
||||||
|
if (!form.length) {
|
||||||
|
throw new Error("excel_form was not found in the customer list page");
|
||||||
|
}
|
||||||
|
|
||||||
|
const action =
|
||||||
|
form.attr("action") ||
|
||||||
|
(() => {
|
||||||
|
const tpl = form.attr("ctm_tpl_excel") || "customer_excel.php";
|
||||||
|
return `/customer/tpl/${tpl}`;
|
||||||
|
})();
|
||||||
|
if (!action) {
|
||||||
|
throw new Error("excel_form action was not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const fields: Record<string, string> = {};
|
||||||
|
form.find("input[name]").each((_, element) => {
|
||||||
|
const input = $(element);
|
||||||
|
const name = input.attr("name");
|
||||||
|
if (!name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fields[name] = input.val()?.toString() ?? "";
|
||||||
|
});
|
||||||
|
|
||||||
|
return { action, fields };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseTotalCount(html: string): number {
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
const explicitValue =
|
||||||
|
$('form[name="excel_form"] input[name="ctm_list_total_cnt"]').val()?.toString() ??
|
||||||
|
$('form[name="search_form"] input[name="ctm_list_total_cnt"]').val()?.toString();
|
||||||
|
|
||||||
|
if (explicitValue) {
|
||||||
|
const parsed = Number(explicitValue.replace(/,/g, ""));
|
||||||
|
if (!Number.isNaN(parsed)) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bodyText = $.text();
|
||||||
|
const match = bodyText.match(/Total\s*[::]\s*([\d,]+)건/i);
|
||||||
|
if (match) {
|
||||||
|
const parsed = Number(match[1].replace(/,/g, ""));
|
||||||
|
if (!Number.isNaN(parsed)) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSearchForm(html: string): Record<string, string> {
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
const form = $('form[name="search_form"]');
|
||||||
|
if (!form.length) {
|
||||||
|
throw new Error("search_form was not found in the customer list page");
|
||||||
|
}
|
||||||
|
|
||||||
|
const fields: Record<string, string> = {};
|
||||||
|
|
||||||
|
form.find("input[name], select[name], textarea[name]").each((_, element) => {
|
||||||
|
const input = $(element);
|
||||||
|
const name = input.attr("name");
|
||||||
|
if (!name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagName = element.tagName.toLowerCase();
|
||||||
|
const type = (input.attr("type") ?? "").toLowerCase();
|
||||||
|
|
||||||
|
if (type === "checkbox" || type === "radio") {
|
||||||
|
if (!input.is(":checked")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fields[name] = input.val()?.toString() ?? "on";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagName === "select") {
|
||||||
|
fields[name] = input.find("option[selected]").val()?.toString() ?? input.val()?.toString() ?? "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fields[name] = input.val()?.toString() ?? "";
|
||||||
|
});
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildFormBody(fields: Record<string, string>): URLSearchParams {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
for (const [name, value] of Object.entries(fields)) {
|
||||||
|
params.set(name, value);
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFileNameFromDisposition(contentDisposition: string | undefined): string | null {
|
||||||
|
if (!contentDisposition) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const decodeFileName = (value: string): string => {
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(value);
|
||||||
|
} catch {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const utf8Match = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i);
|
||||||
|
if (utf8Match) {
|
||||||
|
return decodeFileName(utf8Match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const basicMatch = contentDisposition.match(/filename="?([^"]+)"?/i);
|
||||||
|
if (basicMatch) {
|
||||||
|
return decodeFileName(basicMatch[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toYmd(date: Date): string {
|
||||||
|
return date.toISOString().slice(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMonths(date: Date, months: number): Date {
|
||||||
|
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + months, date.getUTCDate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDays(date: Date, days: number): Date {
|
||||||
|
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function minDate(left: Date, right: Date): Date {
|
||||||
|
return left.getTime() <= right.getTime() ? left : right;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildQuarterRanges(startYmd: string, batchMonths: number): Array<{ start: string; end: string }> {
|
||||||
|
const startDate = new Date(`${startYmd}T00:00:00Z`);
|
||||||
|
const today = new Date();
|
||||||
|
const endDate = new Date(Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate()));
|
||||||
|
|
||||||
|
if (Number.isNaN(startDate.getTime())) {
|
||||||
|
throw new Error(`Invalid BIZMAX_RANGE_START: ${startYmd}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Number.isInteger(batchMonths) || batchMonths <= 0) {
|
||||||
|
throw new Error(`Invalid BIZMAX_BATCH_MONTHS: ${batchMonths}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ranges: Array<{ start: string; end: string }> = [];
|
||||||
|
let rangeStart = startDate;
|
||||||
|
|
||||||
|
while (rangeStart.getTime() <= endDate.getTime()) {
|
||||||
|
const nextRangeStart = addMonths(rangeStart, batchMonths);
|
||||||
|
const rangeEnd = minDate(addDays(nextRangeStart, -1), endDate);
|
||||||
|
ranges.push({ start: toYmd(rangeStart), end: toYmd(rangeEnd) });
|
||||||
|
rangeStart = nextRangeStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
const loginId = getRequiredEnv("BIZMAX_ID", LOGIN_ID);
|
||||||
|
const loginPassword = getRequiredEnv("BIZMAX_PASSWORD", LOGIN_PASSWORD);
|
||||||
|
await mkdir(OUTPUT_DIR, { recursive: true });
|
||||||
|
const ranges = buildQuarterRanges(RANGE_START, BATCH_MONTHS);
|
||||||
|
|
||||||
|
for (const baseUrl of BASE_URLS) {
|
||||||
|
const jar = new SimpleCookieJar();
|
||||||
|
const siteSlug = new URL(baseUrl).hostname.replace(/\./g, "_");
|
||||||
|
|
||||||
|
const loginPageResponse = await request<string>(jar, {
|
||||||
|
method: "GET",
|
||||||
|
url: absoluteUrl(baseUrl, "/"),
|
||||||
|
responseType: "text",
|
||||||
|
});
|
||||||
|
|
||||||
|
const { appName, authStep } = parseLoginPage(loginPageResponse.data);
|
||||||
|
|
||||||
|
const loginBody = new URLSearchParams({
|
||||||
|
from: "pc",
|
||||||
|
nhoj: loginId,
|
||||||
|
mluap: md5(loginPassword),
|
||||||
|
app_name: appName,
|
||||||
|
captcha_str: "",
|
||||||
|
auth_step: authStep,
|
||||||
|
force_sms: "n",
|
||||||
|
});
|
||||||
|
|
||||||
|
const loginResponse = await request<LoginResponse>(jar, {
|
||||||
|
method: "POST",
|
||||||
|
url: absoluteUrl(baseUrl, "/login_pcs_jr.php"),
|
||||||
|
data: loginBody.toString(),
|
||||||
|
responseType: "json",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
Accept: "application/json, text/javascript, */*; q=0.01",
|
||||||
|
Referer: absoluteUrl(baseUrl, "/"),
|
||||||
|
Origin: baseUrl,
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const loginData = loginResponse.data;
|
||||||
|
if (loginData.u_sms_a === "y") {
|
||||||
|
throw new Error(`[${baseUrl}] This account requires SMS verification. Axios-only automation cannot finish that step.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (`${loginData.login_succ ?? ""}` !== "1" || !loginData.f_url) {
|
||||||
|
throw new Error(`[${baseUrl}] Login failed: ${loginData.ret_msg ?? "unknown error"}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mainPageUrl = absoluteUrl(baseUrl, loginData.f_url);
|
||||||
|
await request<string>(jar, {
|
||||||
|
method: "GET",
|
||||||
|
url: mainPageUrl,
|
||||||
|
responseType: "text",
|
||||||
|
headers: {
|
||||||
|
Referer: absoluteUrl(baseUrl, "/"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const customerListResponse = await request<string>(jar, {
|
||||||
|
method: "POST",
|
||||||
|
url: absoluteUrl(baseUrl, CUSTOMER_LIST_PATH),
|
||||||
|
data: new URLSearchParams({
|
||||||
|
_ihr: "n",
|
||||||
|
_ihl: "n",
|
||||||
|
_content_only: "n",
|
||||||
|
site_gubun: "pc",
|
||||||
|
}).toString(),
|
||||||
|
responseType: "text",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
Referer: mainPageUrl,
|
||||||
|
Origin: baseUrl,
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const baseSearchFields = parseSearchForm(customerListResponse.data);
|
||||||
|
|
||||||
|
for (const range of ranges) {
|
||||||
|
const searchFields = {
|
||||||
|
...baseSearchFields,
|
||||||
|
_ihr: "n",
|
||||||
|
_ihl: "n",
|
||||||
|
_content_only: "n",
|
||||||
|
site_gubun: "pc",
|
||||||
|
mode: "search",
|
||||||
|
page: "",
|
||||||
|
use_date_1: "a.reg_date",
|
||||||
|
use_date_1_src: "a.reg_date",
|
||||||
|
use_date_1_dsp: "- 접수일자",
|
||||||
|
start_date_1: range.start,
|
||||||
|
end_date_1: range.end,
|
||||||
|
};
|
||||||
|
|
||||||
|
const rangedCustomerListResponse = await request<string>(jar, {
|
||||||
|
method: "POST",
|
||||||
|
url: absoluteUrl(baseUrl, CUSTOMER_LIST_PATH),
|
||||||
|
data: buildFormBody(searchFields).toString(),
|
||||||
|
responseType: "text",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
Referer: mainPageUrl,
|
||||||
|
Origin: baseUrl,
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalCount = parseTotalCount(rangedCustomerListResponse.data);
|
||||||
|
if (totalCount === 0) {
|
||||||
|
process.stdout.write(`[${siteSlug}] SKIP ${range.start}~${range.end} (0건)\n`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { action, fields } = parseExcelForm(rangedCustomerListResponse.data);
|
||||||
|
fields.e_type = "1";
|
||||||
|
|
||||||
|
const excelResponse = await request<ArrayBuffer>(jar, {
|
||||||
|
method: "POST",
|
||||||
|
url: absoluteUrl(baseUrl, action),
|
||||||
|
data: buildFormBody(fields).toString(),
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
Referer: absoluteUrl(baseUrl, CUSTOMER_LIST_PATH),
|
||||||
|
Origin: baseUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const contentDisposition =
|
||||||
|
typeof excelResponse.headers["content-disposition"] === "string"
|
||||||
|
? excelResponse.headers["content-disposition"]
|
||||||
|
: undefined;
|
||||||
|
const fileName =
|
||||||
|
getFileNameFromDisposition(contentDisposition) ??
|
||||||
|
`bizmax-customer-list-${range.start}-${range.end}.xlsx`;
|
||||||
|
|
||||||
|
const ext = path.extname(fileName);
|
||||||
|
const baseName = ext ? fileName.slice(0, -ext.length) : fileName;
|
||||||
|
const rangedFileName = `${siteSlug}_${baseName}_${range.start}_${range.end}${ext || ".xlsx"}`;
|
||||||
|
const outputPath = path.join(OUTPUT_DIR, rangedFileName);
|
||||||
|
await writeFile(outputPath, Buffer.from(excelResponse.data));
|
||||||
|
|
||||||
|
process.stdout.write(`${outputPath}\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error: unknown) => {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
process.stderr.write(`${message}\n`);
|
||||||
|
process.exitCode = 1;
|
||||||
|
});
|
||||||
106
compare-csv-phone.ts
Normal file
106
compare-csv-phone.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import { readFile, writeFile } from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
import { parse } from "csv-parse/sync";
|
||||||
|
|
||||||
|
const FILE_A = process.env.COMPARE_FILE_A ?? path.resolve(process.cwd(), "a.csv");
|
||||||
|
const FILE_B = process.env.COMPARE_FILE_B ?? path.resolve(process.cwd(), "b.csv");
|
||||||
|
const PHONE_COL_A = process.env.COMPARE_PHONE_COL_A ?? "phone";
|
||||||
|
const PHONE_COL_B = process.env.COMPARE_PHONE_COL_B ?? "phone";
|
||||||
|
const MODE = process.env.COMPARE_MODE ?? "intersection";
|
||||||
|
const OUTPUT_FILE =
|
||||||
|
process.env.COMPARE_OUTPUT_FILE ?? path.resolve(process.cwd(), `compare-${MODE}.csv`);
|
||||||
|
|
||||||
|
type CsvRow = Record<string, string>;
|
||||||
|
|
||||||
|
function normalizePhone(value: string): string {
|
||||||
|
return value.replace(/\D+/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toCsv(rows: CsvRow[]): string {
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = Array.from(
|
||||||
|
rows.reduce((set, row) => {
|
||||||
|
for (const key of Object.keys(row)) {
|
||||||
|
set.add(key);
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}, new Set<string>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
const escape = (value: string): string => {
|
||||||
|
if (/[",\n\r]/.test(value)) {
|
||||||
|
return `"${value.replace(/"/g, "\"\"")}"`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const lines = [headers.join(",")];
|
||||||
|
for (const row of rows) {
|
||||||
|
lines.push(headers.map((header) => escape(row[header] ?? "")).join(","));
|
||||||
|
}
|
||||||
|
return `${lines.join("\n")}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readCsv(filePath: string): Promise<CsvRow[]> {
|
||||||
|
const content = await readFile(filePath, "utf8");
|
||||||
|
return parse(content, {
|
||||||
|
columns: true,
|
||||||
|
skip_empty_lines: true,
|
||||||
|
}) as CsvRow[];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
const [rowsA, rowsB] = await Promise.all([readCsv(FILE_A), readCsv(FILE_B)]);
|
||||||
|
|
||||||
|
const phonesB = new Set(
|
||||||
|
rowsB.map((row) => normalizePhone(row[PHONE_COL_B] ?? "")).filter(Boolean),
|
||||||
|
);
|
||||||
|
|
||||||
|
const matches: CsvRow[] = [];
|
||||||
|
const onlyA: CsvRow[] = [];
|
||||||
|
|
||||||
|
for (const row of rowsA) {
|
||||||
|
const normalized = normalizePhone(row[PHONE_COL_A] ?? "");
|
||||||
|
if (!normalized) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phonesB.has(normalized)) {
|
||||||
|
matches.push({
|
||||||
|
source: "a",
|
||||||
|
normalized_phone: normalized,
|
||||||
|
...row,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
onlyA.push({
|
||||||
|
source: "a",
|
||||||
|
normalized_phone: normalized,
|
||||||
|
...row,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let outputRows: CsvRow[];
|
||||||
|
switch (MODE) {
|
||||||
|
case "intersection":
|
||||||
|
outputRows = matches;
|
||||||
|
break;
|
||||||
|
case "only_a":
|
||||||
|
outputRows = onlyA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported COMPARE_MODE: ${MODE}. Use intersection or only_a.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeFile(OUTPUT_FILE, toCsv(outputRows), "utf8");
|
||||||
|
process.stdout.write(`${OUTPUT_FILE}\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error: unknown) => {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
process.stderr.write(`${message}\n`);
|
||||||
|
process.exitCode = 1;
|
||||||
|
});
|
||||||
91
convert-xlsx-to-csv.ts
Normal file
91
convert-xlsx-to-csv.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import XLSX from "xlsx";
|
||||||
|
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const INPUT_DIR = process.env.BIZMAX_OUTPUT_DIR ?? path.resolve(process.cwd(), "output");
|
||||||
|
const CSV_DIR = process.env.BIZMAX_CSV_DIR ?? path.join(INPUT_DIR, "csv");
|
||||||
|
const CSV_NAME = process.env.BIZMAX_CSV_NAME ?? "bizmax-all.csv";
|
||||||
|
|
||||||
|
function toText(value: unknown): string {
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeCsv(value: string): string {
|
||||||
|
if (/[",\n\r]/.test(value)) {
|
||||||
|
return `"${value.replace(/"/g, "\"\"")}"`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rowToCsv(row: string[]): string {
|
||||||
|
return row.map(escapeCsv).join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
const entries = await readdir(INPUT_DIR, { withFileTypes: true });
|
||||||
|
const xlsxFiles = entries
|
||||||
|
.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".xlsx"))
|
||||||
|
.map((entry) => path.join(INPUT_DIR, entry.name))
|
||||||
|
.sort();
|
||||||
|
|
||||||
|
if (xlsxFiles.length === 0) {
|
||||||
|
throw new Error(`No .xlsx files found in ${INPUT_DIR}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputRows: string[] = [];
|
||||||
|
let wroteHeader = false;
|
||||||
|
|
||||||
|
for (const xlsxFile of xlsxFiles) {
|
||||||
|
const workbook = XLSX.readFile(xlsxFile, { cellDates: false });
|
||||||
|
|
||||||
|
for (const sheetName of workbook.SheetNames) {
|
||||||
|
const worksheet = workbook.Sheets[sheetName];
|
||||||
|
const rows = XLSX.utils.sheet_to_json<unknown[]>(worksheet, {
|
||||||
|
header: 1,
|
||||||
|
raw: false,
|
||||||
|
defval: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (rows.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headerRow = (rows[0] ?? []).map(toText);
|
||||||
|
if (!wroteHeader) {
|
||||||
|
outputRows.push(
|
||||||
|
rowToCsv(["source_file", "source_sheet", ...headerRow]),
|
||||||
|
);
|
||||||
|
wroteHeader = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const row of rows.slice(1)) {
|
||||||
|
const values = (row as unknown[]).map(toText);
|
||||||
|
outputRows.push(
|
||||||
|
rowToCsv([
|
||||||
|
path.basename(xlsxFile),
|
||||||
|
sheetName,
|
||||||
|
...values,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wroteHeader) {
|
||||||
|
throw new Error(`No worksheet rows found in ${INPUT_DIR}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await mkdir(CSV_DIR, { recursive: true });
|
||||||
|
const outputPath = path.join(CSV_DIR, CSV_NAME);
|
||||||
|
await writeFile(outputPath, `${outputRows.join("\n")}\n`, "utf8");
|
||||||
|
process.stdout.write(`${outputPath}\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error: unknown) => {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
process.stderr.write(`${message}\n`);
|
||||||
|
process.exitCode = 1;
|
||||||
|
});
|
||||||
271919
output/csv/bizmax-all.csv
Normal file
271919
output/csv/bizmax-all.csv
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
696
package-lock.json
generated
Normal file
696
package-lock.json
generated
Normal file
@@ -0,0 +1,696 @@
|
|||||||
|
{
|
||||||
|
"name": "download",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.15.0",
|
||||||
|
"cheerio": "^1.2.0",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/adler-32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.15.11",
|
||||||
|
"form-data": "^4.0.5",
|
||||||
|
"proxy-from-env": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/boolbase": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/call-bind-apply-helpers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cfb": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"crc-32": "~1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cheerio": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cheerio-select": "^2.1.0",
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.2.2",
|
||||||
|
"encoding-sniffer": "^0.2.1",
|
||||||
|
"htmlparser2": "^10.1.0",
|
||||||
|
"parse5": "^7.3.0",
|
||||||
|
"parse5-htmlparser2-tree-adapter": "^7.1.0",
|
||||||
|
"parse5-parser-stream": "^7.1.2",
|
||||||
|
"undici": "^7.19.0",
|
||||||
|
"whatwg-mimetype": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.18.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cheerio-select": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-select": "^5.1.0",
|
||||||
|
"css-what": "^6.1.0",
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/codepage": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/crc-32": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"crc32": "bin/crc32.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-select": {
|
||||||
|
"version": "5.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
|
||||||
|
"integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-what": "^6.1.0",
|
||||||
|
"domhandler": "^5.0.2",
|
||||||
|
"domutils": "^3.0.1",
|
||||||
|
"nth-check": "^2.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-what": {
|
||||||
|
"version": "6.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
|
||||||
|
"integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dom-serializer": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.2",
|
||||||
|
"entities": "^4.2.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/domelementtype": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/domhandler": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/domutils": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dunder-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/encoding-sniffer": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"whatwg-encoding": "^3.1.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/entities": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-object-atoms": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-set-tostringtag": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||||
|
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/frac": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"es-define-property": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"dunder-proto": "^1.0.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-tostringtag": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hasown": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/htmlparser2": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.2.2",
|
||||||
|
"entities": "^7.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/htmlparser2/node_modules/entities": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/math-intrinsics": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nth-check": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5": {
|
||||||
|
"version": "7.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
|
||||||
|
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"entities": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5-htmlparser2-tree-adapter": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"parse5": "^7.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5-parser-stream": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"parse5": "^7.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5/node_modules/entities": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/proxy-from-env": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/ssf": {
|
||||||
|
"version": "0.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||||
|
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"frac": "~1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "7.24.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-7.24.7.tgz",
|
||||||
|
"integrity": "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.18.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-encoding": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
|
||||||
|
"deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"iconv-lite": "0.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-mimetype": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wmf": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/word": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xlsx": {
|
||||||
|
"version": "0.18.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
|
||||||
|
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"cfb": "~1.2.1",
|
||||||
|
"codepage": "~1.15.0",
|
||||||
|
"crc-32": "~1.2.1",
|
||||||
|
"ssf": "~0.11.2",
|
||||||
|
"wmf": "~1.0.1",
|
||||||
|
"word": "~0.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"xlsx": "bin/xlsx.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
package.json
Normal file
9
package.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.15.0",
|
||||||
|
"cheerio": "^1.2.0",
|
||||||
|
"csv-parse": "^5.5.6",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
37
run-bizmax.sh
Executable file
37
run-bizmax.sh
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ENV_FILE="${BIZMAX_ENV_FILE:-$SCRIPT_DIR/.env}"
|
||||||
|
TARGET="${1:-all}"
|
||||||
|
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$TARGET" in
|
||||||
|
hyun)
|
||||||
|
BASE_URLS="https://hyun.bizmax.net"
|
||||||
|
;;
|
||||||
|
hyun2)
|
||||||
|
BASE_URLS="https://hyun2.bizmax.net"
|
||||||
|
;;
|
||||||
|
all)
|
||||||
|
BASE_URLS="https://hyun.bizmax.net,https://hyun2.bizmax.net"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 [hyun|hyun2|all]" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ -z "${BIZMAX_ID:-}" || -z "${BIZMAX_PASSWORD:-}" ]]; then
|
||||||
|
echo "Set BIZMAX_ID and BIZMAX_PASSWORD before running." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BIZMAX_BASE_URLS="$BASE_URLS" \
|
||||||
|
node --experimental-strip-types "$SCRIPT_DIR/bizmax-download-excel.ts"
|
||||||
14
run-compare-csv.sh
Executable file
14
run-compare-csv.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ENV_FILE="${BIZMAX_ENV_FILE:-$SCRIPT_DIR/.env}"
|
||||||
|
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
node --experimental-strip-types "$SCRIPT_DIR/compare-csv-phone.ts"
|
||||||
14
run-convert-csv.sh
Executable file
14
run-convert-csv.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ENV_FILE="${BIZMAX_ENV_FILE:-$SCRIPT_DIR/.env}"
|
||||||
|
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
node --experimental-strip-types "$SCRIPT_DIR/convert-xlsx-to-csv.ts"
|
||||||
20
run-hyun.sh
Executable file
20
run-hyun.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ENV_FILE="${BIZMAX_ENV_FILE:-$SCRIPT_DIR/.env}"
|
||||||
|
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${BIZMAX_ID:-}" || -z "${BIZMAX_PASSWORD:-}" ]]; then
|
||||||
|
echo "Set BIZMAX_ID and BIZMAX_PASSWORD before running." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BIZMAX_BASE_URLS="https://hyun.bizmax.net" \
|
||||||
|
node --experimental-strip-types "$SCRIPT_DIR/bizmax-download-excel.ts"
|
||||||
20
run-hyun2.sh
Executable file
20
run-hyun2.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ENV_FILE="${BIZMAX_ENV_FILE:-$SCRIPT_DIR/.env}"
|
||||||
|
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${BIZMAX_ID:-}" || -z "${BIZMAX_PASSWORD:-}" ]]; then
|
||||||
|
echo "Set BIZMAX_ID and BIZMAX_PASSWORD before running." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BIZMAX_BASE_URLS="https://hyun2.bizmax.net" \
|
||||||
|
node --experimental-strip-types "$SCRIPT_DIR/bizmax-download-excel.ts"
|
||||||
Reference in New Issue
Block a user