동적 웹을 스크래핑하는 과정은 필수적으로 JS 렌더링이 필요하기 때문에 그 부하가 크고 시간이 오래 걸린다.
이전에 Selenium을 썼지만 이 녀석, 너무 느리다.
내 아마존 프리티어 VM이 감당하기엔 너무 큰 짐이 아니었나 싶기도 하다.
그래서 아래와 같은 방법들을 모색해 봤다.
1. 클라우드 변경
조금 더 속도가 빠른 클라우드를 찾기 위해 구글링을 거듭했다.
약간의 돈이라면 지불할 용의도 있었다.
그러다 문득 뇌리에 스친 Oracle Cloud.
1개의 OCPU를 제공한다는 뜻은 2개의 스레드를 돌릴 수 있다는 뜻이다.
일정 사용량을 초과하지만 않으면 평생 무료이기도 하니 이것으로 낙점.
한 달짜리 무료 크레딧도 받은 김에 12 코어짜리 VM도 설정했다.
내 봇엔 너무 과한 스펙이지만 어차피 사라질 크레딧이다. 이렇게라도 써보자. 언제 비싼 VM을 써보겠는가?
Oracle Cloud 사용에 관한건 추후 별도의 글에서 서술.
2. 브라우저 최적화
지금 pyppeteer를 최초 실행 후, 해당 엔드포인트를 넘겨줘 하나의 브라우저 인스턴스를 돌려쓸 수 있게 해 놓았다.
그래서 그 돌려쓰는 브라우저가 최대한 가벼워야 로딩도 빨라지고 시스템 자원도 덜 먹고 해서 좋지 않겠는가?
async def intercept_request(request):
blocked_resource_types = ["image", "stylesheet", "font"]
if request.resourceType in blocked_resource_types:
await request.abort()
else:
await request.continue_()
async def ppEndpoint(self):
if self.ppWsEndpoint is None:
browser_args = [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-accelerated-2d-canvas",
"--no-first-run",
"--disable-gpu",
"--disable-background-networking",
"--disable-extensions",
"--disable-translate",
"--disable-hang-monitor",
"--mute-audio",
"--disable-popup-blocking",
"--disable-notifications",
"--disable-gpu-program-cache",
"--disable-dev-shm-usage",
"--no-default-browser-check",
"--hide-scrollbars",
"--disable-software-rasterizer",
"--disable-skia-runtime-opts",
"--user-data-dir=./pyppCache"
]
self.browser = await pyppeteer.launch(headless=True, args = browser_args)
# Getting a page to set request interception
page = await self.browser.newPage()
await page.setRequestInterception(True)
page.on('request', lambda req: asyncio.ensure_future(self.intercept_request(req)))
self.ppWsEndpoint = self.browser.wsEndpoint
await self.browser.disconnect()
Logger.info(f"Pyppeteer WebSocket Endpoint: {self.ppWsEndpoint}")
return self.ppWsEndpoint
GPT와 구글의 힘을 빌어 헤드리스 모드에서 효과가 있을 법 한 옵션들을 죄다 긁어왔다.
근데 효과가 있는지는 잘... 모르겠다.
데스크탑 환경이라 하드웨어 스펙이 부족하지 않기 때문에 티가 나지 않는 걸 수도 있겠다.
3. 병렬 처리
스레드가 2개가 됐으니 벙렬처리에 눈을 돌려봅 법하다.
지금 ETF 리스트에 있는 ETF는 6개.
스레드가 2개니 2개의 스레드가 각각 3개씩 담당하게 할 수도 있다.
3개의 스레드를 만들어서 2개씩만 처리하게 할 수도 있겠다.
일단 데스크탑에서 테스트를 진행하기 때문에 6개 스레드를 통해 하나씩 처리하게 만들었으나,
알 수 없는 문제로 인해 제대로 동작하지 않았다.
아마도 하나의 인스턴스에 대해 너무 큰 부하였을 수도 있겠다.
3개의 스레드를 통해 2개씩 처리하게 만드는 것이 꽤 괜찮았다.
대충 위와 비슷한 시간이 걸렸다.
원래 8 ~ 10초가량 걸렸었는데 확실히 병렬 처리에 이점이 있다.
하지만 초기 실행 및 실행 간 텀이 있을 때 크롬이 자체적으로 리소스 관리를 하기에,
연속적 실행이 아닐 경우 20초 이상의 시간이 걸릴 수 있다는 것은 상당한 문제다.
야후 금융이 아니라 다른 가벼운 사이트를 통해 데이터를 긁어오는 것이 옳을 수도 있겠다.
yfinance 패키지는 물론 다른 야후 금융 API에 의존하는 패키지들이 많은 네트워크 환경에서 사용하기 어렵기 됐기 때문에 스크래핑에 의존할 수밖에 없겠다.
'Study > Python' 카테고리의 다른 글
[Python] Pyppeteer를 버리다 (0) | 2023.10.25 |
---|---|
[Python] Aim Smoothing (0) | 2023.10.19 |
[Python] 봇 개선 및 커맨드 추가 (0) | 2023.10.16 |
[Python] 웹 파싱 / 기존 기능 개선 (0) | 2023.08.11 |
[Python] DeepL 번역 API 써보기 (0) | 2023.06.02 |