누구나 할 수 있는 크롤링 #1

Eugene Lim
8 min readJul 20, 2024

--

누구나 할 수 있는 크롤링 #2

동생이 특정 브랜드의 옷을 좋아하는데, 항상 세일을 늦게 알게 되어서 구매를 놓친다고 했다. 그래서 동생을 위해 간단한 웹크롤링을 적용한 프로젝트를 해보기로 했다.

어떻게 구현할 수 있을지 생각해본다.

  1. 내가 액션을 하지 않아야 함
  2. 화면을 자동으로 읽어야 함
  3. 이 읽은 데이터 중에 내가 원하는 부분을 나에게 알려줘야 함

그럼 이 문제를 해결할 수 있는 기술은 이정도가 될 것 같다

  • 특정 시간마다 자동으로 스크립트를 돌릴 crontab 또는 스케줄러
  • html parsing
  • 내 핸드폰으로 서머리를 전송

그럼 필요한 tech spec 은,

  1. scheduler — firebase function
  2. html parsing — python + beautifulsoup
  3. send summary messages — slack api

이정도면 꽤 어렵지 않게 구현할 수 있을 것 같다.

작업을 시작해보자.

파싱할 페이지를 찾는다.

나는 동생이 좋아하는 옷의 홈페이지 중 세일 페이지를 선택했다

https://www.ssfshop.com/Maison-Kitsune/On-Sale/list?dspCtgryNo=SFMA33&brandShopNo=BDMA07A22&brndShopId=BQMKT

개발환경을 구성해보자

요즘 vscode로 python 개발을 많이하니 다운로드를 한다.

왼쪽 메뉴 중 아래에서 2번째 사각형이 4개 있는 아이콘
아래에서 2번째 아이콘(사각형이 4개 있는 아이콘 — 익스텐션)

다운로드 이후에 python extension도 설치해준다.

python SDK 버전은 3.11.6으로 했다.

⚠️ 현재 python 3.12가 최신이지만, 나중에 사용할 firebase function에서 python 3.11까지만 지원하고 있어서 3.11.6으로 설정했다.
firebase function 환경설정

File -> New File 을 선택한 후에 파일 이름을 “test.py”로 하고

print("Hello World!")

그 이후에 상단 오른쪽 ▶ 버튼을 클릭해서 실행해보자!

하단 화면에 Hello World! 가 프린트되는 것을 확인할 수 있다.

python 라이브러리 선택

  • requests — http 통신을 쉽게 해주는 라이브러리
  • beautifulsoup4 — html 파싱을 해주는 라이브러리
$ python3 -m pip install requests==2.31.0
$ pyyhon4 -m pip install beautifulsoup4==4.12.2

라이브러리를 설치하고 이제 함수를 만들어보자.

def hello_world():
print("Hello, world!")
return

hello_world()

이제 기본적인 준비는 다 되었다.

requests lib를 통해 html을 잘 가져오는지 확인해보자.

import requests

def check_web():
url = "{내가 파싱하려는 url}"
page = requests.get(url)
print(page.text) # <- html이 나오는 것을 확인할 수 있다

check_web()

html도 잘 나오는 것을 확인했다!

이제 html의 어느 부분을 값을 확인해야하는지를 찾아야 한다. 크롬으로 웹페이지를 열고 F12 를 클릭하면 오른쪽에 html이 나오는 것을 확인할 수 있다. 여기서 내가 원하는 부분을 왼쪽 화면에서 클릭하면 html 중 어느 부분에서 이 영역을 표시하는지 확인할 수 있다.

여기서 30%할인이 표시되는 아이템들의 리스트를 찾고 싶다
<div class="info">
...
<em class="sale">
...
"30%" <-- <em> 태그안의 텍스트를 가져오면 몇 퍼센트 할인을 하는지 알 수 있다
</em>
</div>

그런데 우리는 이 화면에 나오는 모든 리스트 중 30%이상의 아이템만 뽑고 싶기 때문에 각 아이템들을 전부 탐색해야한다. 그럼 ▼ 아래로 펼쳐져있는 세모 아이콘을 클릭해서 한 번 접어보자. 그럼 다음처럼 모든 리스트를 볼 수 있다.

list_goods까지 올라가보면 왼쪽 리스트가 전부 선택된 것을 볼 수 있다
<div class="list_goods">
<ul>
<li>첫번째 아이템</li>
<li>두번째 아이템들</li>
...
</ul>
</div>

결국 list_goods를 찾아서 그 안의 아이템들을 모두 한 번씩 확인하면 우리가 원하는 30%이상 할인하는 아이템을 찾을 수 있다!

import requests
from bs4 import BeautifulSoup # <- 이제 beatifulsoup을 이용해서 html을 파싱해보자

def check_web():
url = "{내가 파싱하려는 url}"
page = requests.get(url)
soup = BeautifulSoup(page.text, 'html.parser')

# select로 .list_goods 아래 ul 아래 li의 리스트를 받을 수 있다
list = soup.select('.list_goods > ul > li')
for good in list:
print(good) # 여기까지 잘 왔나 한 번 아이템을 프린트 해본다

check_web()

너무 많이 나와서 뭔가 찍히는 것 같다. 그럼 아이템 이름과 가격을 한 번 print 해보자.

import requests
from bs4 import BeautifulSoup # <- 이제 beatifulsoup을 이용해서 html을 파싱해보자

def check_web():
url = "{내가 파싱하려는 url}"
page = requests.get(url)
soup = BeautifulSoup(page.text, 'html.parser')

list = soup.select('.list_goods > ul > li')
for good in list:
name = good.select('.name')
sale = good.find('span', {'class':'price'}) # span tag 중에 class=price를 찾는다
print("name =", name) # 각 아이템의 이름
print("sale =", sale) # 각 아이템의 가격


check_web()

good.find() 를 쓰면 good 객체 아래로 하위 태그들을 array로 접근할 수 있게 해준다.

contents 가 배열이다
sale.contents[2] # 395,000
sale.contents[7] # 할인율 30%

이제 파싱은 거의 끝났다.

won = sale.contents[2].get_text().strip() # \t를 없애주기 위에 strip()을 썼다
percentage = sale.contents[7] # 할인율 30%
discount = sale.contents[7].contents[1] # 30%까지 찾는다

30%에서 30만 뽑아서 할인율을 체크해야하므로, 숫자를 뽑아내는 함수를 하나 추가한다.

def extract_number(text):
"""Extracts the number from a string.

Args:
text: A string.

Returns:
The number extracted from the string, or None if no number is found.
"""

match = re.search(r'\d+', text)
if match:
return int(match.group())
else:
return None


discount = extract_number(discount) # 30이라는 숫자가 나오고
if discount >= 30:
# 이 아이템을 이제 슬랙으로 전송하면 된다

슬랙으로 전송하는 부분은 다음 포스팅으로 ..

--

--