-
-
Save listly-io/6bfce54ea1396c0714675a82e0a238f6 to your computer and use it in GitHub Desktop.
lazada_review_pagination_2025-10-24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ======================================== | |
| // 사용자 설정 변수 | |
| // ======================================== | |
| // 수집할 페이지 수 (현재 페이지 포함) | |
| const MAX_PAGE_COUNT = 22; | |
| // 페이지 전환 후 대기 시간 (밀리초) | |
| const WAIT_TIME = 5000; | |
| // 스크롤 후 대기 시간 (밀리초) | |
| const SCROLL_WAIT_TIME = 1000; | |
| // 리뷰 아이템 CSS Selector | |
| const REVIEW_ITEM_SELECTOR = '#module_product_review DIV[class="item"]'; | |
| // 페이지네이션 영역 Selector | |
| const PAGINATION_SELECTOR = 'ul.iweb-pagination'; | |
| // ======================================== | |
| // 메인 로직 | |
| // ======================================== | |
| (async function collectReviews() { | |
| console.log('=== 리뷰 수집 시작 ==='); | |
| // 결과를 저장할 컨테이너를 body의 마지막 자식으로 추가 | |
| const container = document.createElement('div'); | |
| container.id = 'review-collection-container'; | |
| container.style.cssText = ` | |
| position: fixed; | |
| bottom: 200px; | |
| right: 10px; | |
| background: white; | |
| border: 2px solid #333; | |
| padding: 10px; | |
| border-radius: 5px; | |
| font-family: monospace; | |
| font-size: 14px; | |
| z-index: 10000; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.3); | |
| `; | |
| document.body.appendChild(container); | |
| let collectedCount = 0; | |
| // 수집 함수 | |
| async function collectCurrentPage() { | |
| console.log(`페이지 ${collectedCount + 1} 수집 중...`); | |
| // 현재 페이지의 모든 리뷰 아이템 찾기 | |
| const reviewItems = document.querySelectorAll(REVIEW_ITEM_SELECTOR); | |
| console.log(` - 발견된 리뷰 수: ${reviewItems.length}개`); | |
| // 각 리뷰 아이템의 HTML을 컨테이너에 추가 (display:none으로 숨김) | |
| reviewItems.forEach((item, index) => { | |
| const reviewDiv = document.createElement('div'); | |
| reviewDiv.className = 'collected-review'; | |
| reviewDiv.style.display = 'none'; | |
| reviewDiv.setAttribute('data-page', collectedCount + 1); | |
| reviewDiv.setAttribute('data-review-index', index + 1); | |
| reviewDiv.innerHTML = item.outerHTML; | |
| container.appendChild(reviewDiv); | |
| }); | |
| collectedCount++; | |
| // 상태 표시 업데이트 | |
| updateStatus(); | |
| // 목표 수집 횟수에 도달했는지 확인 | |
| if (collectedCount >= MAX_PAGE_COUNT) { | |
| console.log('=== 수집 완료 ==='); | |
| console.log(`총 ${getTotalCollectedReviews()}개의 리뷰 수집됨`); | |
| console.log('수집된 HTML은 #review-collection-container 안에 저장되어 있습니다.'); | |
| console.log('다음 명령으로 수집된 리뷰 HTML을 확인할 수 있습니다:'); | |
| console.log(' Array.from(document.querySelectorAll("#review-collection-container > .collected-review")).map(el => el.innerHTML).join("")'); | |
| return; | |
| } | |
| // 다음 페이지로 이동 | |
| if (!(await goToNextPage())) { | |
| console.log('다음 페이지를 찾을 수 없습니다. 수집을 중단합니다.'); | |
| return; | |
| } | |
| // 페이지 로딩 대기 | |
| console.log(` - ${WAIT_TIME / 1000}초 대기 중...`); | |
| await sleep(WAIT_TIME); | |
| // 재귀 호출로 다음 페이지 수집 | |
| await collectCurrentPage(); | |
| } | |
| // 다음 페이지로 이동하는 함수 | |
| async function goToNextPage() { | |
| // 현재 활성화된 페이지 번호 찾기 | |
| const activePage = document.querySelector('.iweb-pagination-item-active'); | |
| if (!activePage) { | |
| console.error('현재 페이지를 찾을 수 없습니다.'); | |
| return false; | |
| } | |
| const currentPageNum = parseInt(activePage.textContent.trim()); | |
| console.log(` - 현재 페이지: ${currentPageNum}`); | |
| // 다음 페이지 번호 | |
| const nextPageNum = currentPageNum + 1; | |
| // 페이지네이션 영역으로 스크롤 | |
| const paginationElement = document.querySelector(PAGINATION_SELECTOR); | |
| if (paginationElement) { | |
| console.log(' - 페이지네이션 영역으로 스크롤...'); | |
| paginationElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); | |
| await sleep(SCROLL_WAIT_TIME); | |
| } | |
| // 다음 페이지 링크 찾기 | |
| const nextPageLink = document.querySelector(`.iweb-pagination-item-${nextPageNum} a`); | |
| if (nextPageLink) { | |
| console.log(` - 다음 페이지(${nextPageNum})로 이동`); | |
| nextPageLink.click(); | |
| return true; | |
| } | |
| // 특정 페이지 번호가 없으면 "Next Page" 버튼 시도 | |
| const nextButton = document.querySelector('.iweb-pagination-next button'); | |
| if (nextButton && !nextButton.closest('.iweb-pagination-next').classList.contains('iweb-pagination-disabled')) { | |
| console.log(' - Next 버튼 클릭'); | |
| nextButton.click(); | |
| return true; | |
| } | |
| return false; | |
| } | |
| // 상태 업데이트 함수 | |
| function updateStatus() { | |
| const totalReviews = getTotalCollectedReviews(); | |
| // 기존 수집된 리뷰들을 임시로 저장 | |
| const collectedReviews = Array.from(container.querySelectorAll('.collected-review')); | |
| // 상태 표시만 업데이트 | |
| container.innerHTML = ` | |
| <div style="margin-bottom: 5px; font-weight: bold;">📊 리뷰 수집 현황</div> | |
| <div>수집된 페이지: ${collectedCount} / ${MAX_PAGE_COUNT}</div> | |
| <div>총 리뷰 수: ${totalReviews}개</div> | |
| `; | |
| // 수집된 리뷰들을 다시 추가 | |
| collectedReviews.forEach(review => { | |
| container.appendChild(review); | |
| }); | |
| } | |
| // 총 수집된 리뷰 개수 계산 | |
| function getTotalCollectedReviews() { | |
| return container.querySelectorAll('.collected-review').length; | |
| } | |
| // Sleep 유틸리티 함수 | |
| function sleep(ms) { | |
| return new Promise(resolve => setTimeout(resolve, ms)); | |
| } | |
| // 수집 시작 | |
| await collectCurrentPage(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment