세션 관리
Crawlee에서 SessionPool
은 프록시 IP 주소와 쿠키, 그리고 기타 사용자 정의 설정의 로테이션을 처리할 수 있게 해주는 클래스입니다.
SessionPool을 사용하면 차단되거나 작동하지 않는 프록시를 필터링할 수 있어, 액터가 이미 알려진 차단/비작동 프록시를 통해 불필요한 재시도를 하지 않는다는 장점이 있습니다. 또한 쿠키, 인증 토큰, 특정 헤더와 같이 IP 주소와 밀접하게 연관된 정보를 저장할 수 있습니다. 특정 IP에서만 쿠키와 식별자를 사용함으로써 차단될 가능성을 줄일 수 있습니다. 마지막으로, IP 주소의 균등한 로테이션이 가능합니다 - SessionPool은 무작위로 세션을 선택하므로 사용 가능한 IP 풀이 작더라도 특정 IP가 과도하게 사용되는 것을 방지할 수 있습니다.
차단 방지에 대한 자세한 내용은 차단 방지 가이드를 참조하세요.
다음은 Session pool 사용 예시입니다:
BasicCrawler
와 함께 사용HttpCrawler
와 함께 사용CheerioCrawler
와 함께 사용JSDOMCrawler
와 함께 사용PlaywrightCrawler
와 함께 사용PuppeteerCrawler
와 함께 사용- 크롤러 없이 독립적으로 세션 수동 관리
- BasicCrawler
- HttpCrawler
- CheerioCrawler
- JSDOMCrawler
- PlaywrightCrawler
- PuppeteerCrawler
- 독립 실행
import { BasicCrawler, ProxyConfiguration } from 'crawlee';
import { gotScraping } from 'got-scraping';
const proxyConfiguration = new ProxyConfiguration({
/* opts */
});
const crawler = new BasicCrawler({
// 세션 풀 활성화 (기본값은 true).
useSessionPool: true,
// 기본 세션 풀 구성 재정의.
sessionPoolOptions: { maxPoolSize: 100 },
async requestHandler({ request, session }) {
const { url } = request;
const requestOptions = {
url,
// 동일한 세션에서 모든 요청에 동일한 proxyUrl을 사용하기 위해 세션 ID를 사용합니다.
proxyUrl: await proxyConfiguration.newUrl(session.id),
throwHttpErrors: false,
headers: {
// 쿠키JAR를 사용하려면
// 이렇게 하면 세션에서 Cookie 헤더 문자열을 가져옵니다.
Cookie: session.getCookieString(url),
},
};
let response;
try {
response = await gotScraping(requestOptions);
} catch (e) {
if (e === 'SomeNetworkError') {
// 네트워크 오류가 발생하면(예: 타임아웃, 소켓 종료 등)
// 일반적으로 그것이 단지 운이 나쁘다는 것이므로
// 프록시가 작동하고 있습니다. 던지지 않아도 됩니다.
session.markBad();
}
throw e;
}
// 응답 HTTP 상태 코드에 따라 세션 자동 재시도.
session.retireOnBlockedStatusCodes(response.statusCode);
if (response.body.blocked) {
// 확실히 차단되었습니다.
// 이것은 세션을 버립니다.
session.retire();
}
// 모든 것이 좋습니다. 데이터를 가져올 수 있습니다.
// 세션.markGood 호출이 필요하지 않습니다. BasicCrawler가 그것을 호출합니다.
// 세션에서 쿠키JAR를 사용하려면 필요합니다.
session.setCookiesFromResponse(response);
},
});
import { HttpCrawler, ProxyConfiguration } from 'crawlee';
const proxyConfiguration = new ProxyConfiguration({
/* opts */
});
const crawler = new HttpCrawler({
// 프록시 IP 세션 회전 논리를 사용하려면 프록시 사용을 켜야 합니다.
proxyConfiguration,
// 세션 풀 활성화 (기본값은 true).
useSessionPool: true,
// 기본 세션 풀 구성 재정의.
sessionPoolOptions: { maxPoolSize: 100 },
// 크롤러가 세션별로 쿠키를 저장하려면 true로 설정하고,
// 쿠키 헤더를 요청에 자동으로 설정합니다(기본값은 true).
persistCookiesPerSession: true,
async requestHandler({ session, body }) {
const title = body.match(/<title(?:.*?)>(.*?)<\/title>/)?.[1];
if (title === 'Blocked') {
session.retire();
} else if (title === 'Not sure if blocked, might also be a connection error') {
session.markBad();
} else {
// session.markGood() - 이 단계는 BasicCrawler에서 자동으로 수행됩니다.
}
},
});
import { CheerioCrawler, ProxyConfiguration } from 'crawlee';
const proxyConfiguration = new ProxyConfiguration({
/* opts */
});
const crawler = new CheerioCrawler({
// 프록시 IP 세션 회전 논리를 사용하려면 프록시 사용을 켜야 합니다.
proxyConfiguration,
// 세션 풀 활성화 (기본값은 true).
useSessionPool: true,
// 기본 세션 풀 구성 재정의.
sessionPoolOptions: { maxPoolSize: 100 },
// 크롤러가 세션별로 쿠키를 저장하려면 true로 설정하고,
// 쿠키 헤더를 요청에 자동으로 설정합니다(기본값은 true).
persistCookiesPerSession: true,
async requestHandler({ session, $ }) {
const title = $('title').text();
if (title === 'Blocked') {
session.retire();
} else if (title === 'Not sure if blocked, might also be a connection error') {
session.markBad();
} else {
// session.markGood() - 이 단계는 BasicCrawler에서 자동으로 수행됩니다.
}
},
});
import { JSDOMCrawler, ProxyConfiguration } from 'crawlee';
const proxyConfiguration = new ProxyConfiguration({
/* opts */
});
const crawler = new JSDOMCrawler({
// 프록시 IP 세션 회전 논리를 사용하려면 프록시 사용을 켜야 합니다.
proxyConfiguration,
// 세션 풀 활성화 (기본값은 true).
useSessionPool: true,
// 기본 세션 풀 구성 재정의.
sessionPoolOptions: { maxPoolSize: 100 },
// 크롤러가 세션별로 쿠키를 저장하려면 true로 설정하고,
// 쿠키 헤더를 요청에 자동으로 설정합니다(기본값은 true).
persistCookiesPerSession: true,
async requestHandler({ session, window }) {
const title = window.document.title;
if (title === 'Blocked') {
session.retire();
} else if (title === 'Not sure if blocked, might also be a connection error') {
session.markBad();
} else {
// session.markGood() - 이 단계는 BasicCrawler에서 자동으로 수행됩니다.
}
},
});
import { PlaywrightCrawler, ProxyConfiguration } from 'crawlee';
const proxyConfiguration = new ProxyConfiguration({
/* opts */
});
const crawler = new PlaywrightCrawler({
// 프록시 IP 세션 회전 논리를 사용하려면 프록시 사용을 켜야 합니다.
proxyConfiguration,
// 세션 풀 활성화 (기본값은 true).
useSessionPool: true,
// 기본 세션 풀 구성 재정의.
sessionPoolOptions: { maxPoolSize: 100 },
// 크롤러가 세션별로 쿠키를 저장하려면 true로 설정하고,
// 탐색 전에 페이지에 쿠키를 설정합니다(기본값은 true).
persistCookiesPerSession: true,
async requestHandler({ page, session }) {
const title = await page.title();
if (title === 'Blocked') {
session.retire();
} else if (title === 'Not sure if blocked, might also be a connection error') {
session.markBad();
} else {
// session.markGood() - 이 단계는 PlaywrightCrawler에서 자동으로 수행됩니다.
}
},
});
import { PuppeteerCrawler, ProxyConfiguration } from 'crawlee';
const proxyConfiguration = new ProxyConfiguration({
/* opts */
});
const crawler = new PuppeteerCrawler({
// 프록시 IP 세션 회전 논리를 사용하려면 프록시 사용을 켜야 합니다.
proxyConfiguration,
// 세션 풀 활성화 (기본값은 true).
useSessionPool: true,
// 기본 세션 풀 구성 재정의.
sessionPoolOptions: { maxPoolSize: 100 },
// 크롤러가 세션별로 쿠키를 저장하려면 true로 설정하고,
// 탐색 전에 페이지에 쿠키를 설정합니다(기본값은 true).
persistCookiesPerSession: true,
async requestHandler({ page, session }) {
const title = await page.title();
if (title === 'Blocked') {
session.retire();
} else if (title === 'Not sure if blocked, might also be a connection error') {
session.markBad();
} else {
// session.markGood() - 이 단계는 PuppeteerCrawler에서 자동으로 수행됩니다.
}
},
});
import { SessionPool } from 'crawlee';
// 기본 세션 풀 구성 재정의.
const sessionPoolOptions = {
maxPoolSize: 100,
};
// 세션 풀 열기.
const sessionPool = await SessionPool.open(sessionPoolOptions);
// 세션 가져오기.
const session = await sessionPool.getSession();
// 오류 점수 증가.
session.markBad();
// 세션 버리기.
session.retire();
// 오류 점수 감소 및 세션 좋음 표시.
session.markGood();
이상이 SessionPool 구성의 기본 사항입니다. Session pool이 작동하는 IP를 찾고 풀을 구축하는 데 시간이 필요하므로, 안정화될 때까지는 많은 오류가 발생할 수 있다는 점을 유의해 주세요.