Coding/Toy Project

[python] 웹 크롤링으로 게시판 업데이트 확인하기 (1)

계기

데스크탑을 사고 싶어서 핫딜을 알아보고 싶은데, 핫딜 게시판을 주기적으로 들르자니 너무 귀찮았다. RSS 느낌으로다가 게시판이 업데이트되면 terminal 수준에서 알려주는 어플리케이션을 만들면 편할 것 같았다. 언어는 가장 빠르게 구현할 수 있는 python으로 선택했다.

목표

특정 사이트게시물 리스트5분 간격으로 탐색하고 업데이트돤 내용만을 추려서 보여준다.

구현

먼저 웹 크롤링에 필요한 모듈을 다운로드한다.

pip install requests, beautifulsoup4
requests => 서버에 웹페이지 내용을 요구할 수 있게 해준다. urlopen을 쓸 예정.
beautifulsoup4 => requests를 통해 얻은 웹페이지 내용을 쓰기 좋게 다듬어준다.

해당 url을 urlopen을 통해 가져오고, 그 결과를 beautiful soup 클래스로 만들어줘서 쓰기 좋게 바꾼다.

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("https://quasarzone.com/bbs/qb_saleinfo")
bsObject = BeautifulSoup(html, "html.parser")

이렇게 전체 페이지는 얻어왔는데, 우리가 필요한 정보는 게시판의 게시물 리스트 중 그 제목이다.
딱 그거만 찾아내기 위해서는 얻어온 html을 좀 둘러볼 필요가 있다.
Chrome의 개발자 도구를 통해 제목에 해당하는 html element가 유일하게 가지고 있는 걸 찾아보자.
찾아보면 해당 문장이 span이라는 태그로 감싸져 있고 class는 ellipsis-with-reply-cnt라는 걸 알 수 있다.
beautiful soup을 통해 딱 그거만 추려내준다.

for span in bsObject.find_all('span', {'class':'ellipsis-with-reply-cnt'}):
	print(span.text)

이 6줄의 코드만 돌려보면 글 제목들이 나열돼 있는 걸 확인할 수 있다.
이제 5분에 한번씩 내용을 가져오도록 바꿔보자.

from urllib.request import urlopen
from bs4 import BeautifulSoup
import time

while True:
	html = urlopen("https://quasarzone.com/bbs/qb_saleinfo")
	bsObject = BeautifulSoup(html, "html.parser")
	for span in bsObject.find_all('span', {'class':'ellipsis-with-reply-cnt'}):
		print(span.text)
	time.sleep(300)

이제 글 제목을 받아오는 것까진 성공했다. 이제 필요한 기능은 업데이트 내용만을 보여주는 것이다. 여기서 관건은 '어떻게 업데이트를 판별하는가'이다. 다양한 방법이 있겠지만 여기서는 최대한 간단하게 구현할 것이다. 알고리즘은 다음과 같다.

1. 매 request마다 가장 상단의 게시물을 저장한다.
2. 이후 request부터는 그 게시물과 내용을 비교해서 같다면 더이상 for을 돌지도 않는다. 만약 다르다면 이전 상단 게시물이 나올때까지 프린트해준다.

위의 알고리즘을 적용하고 코드를 좀 정돈하면 다음과 같다.

from urllib.request import urlopen
from bs4 import BeautifulSoup
import time

site_url = "https://quasarzone.com/bbs/qb_saleinfo"
latest_title = ""

while True:
	html = urlopen(site_url)
	bsObject = BeautifulSoup(html, "html.parser")
	titles = bsObject.find_all('span', {'class':'ellipsis-with-reply-cnt'})
	
	# 업데이트 내용이 있다면 그 내용까지 출력한다.
	if latest_title != titles[0].text:
		print("<--- Update detected --->")
		for t in titles:
			if t.text != latest_title:
				print(t.text)
			else:
				break
		latest_title = titles[0].text # 현재 시점에서 최신 게시물이름을 저장한다.
		print("=====================================")
	else:
		print("<--- No update in", site_url, "--->")
	time.sleep(300)

추후 계획

발전 방향 후보
1. 여러 사이트를 한 코드를 통해 추적한다.
2. 발견된 업데이트 항목의 url을 요청 시에 바로 열 수 있도록 한다.
3. 쉘 수준에서 색깔을 입혀 프린트한다.

'Coding > Toy Project' 카테고리의 다른 글

[Ray Tracing in C] 2. 벡터  (0) 2021.04.13
[Raytracing in C] 1. 준비  (0) 2021.04.12