Skip to content

Instantly share code, notes, and snippets.

@listly-io
Last active November 3, 2025 08:40
Show Gist options
  • Select an option

  • Save listly-io/6bfce54ea1396c0714675a82e0a238f6 to your computer and use it in GitHub Desktop.

Select an option

Save listly-io/6bfce54ea1396c0714675a82e0a238f6 to your computer and use it in GitHub Desktop.
lazada_review_pagination_2025-10-24
// ========================================
// 사용자 설정 변수
// ========================================
// 수집할 페이지 수 (현재 페이지 포함)
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