본문 바로가기
인공지능/Generative AI

[3탄] Beautifulsoup로 웹 크롤링하기

by 유일리 2023. 9. 20.

오늘은  HTML과 XML 문서들의 구문을 분석하기 위한 파이썬 라이브러리Beautifulsoup를 사용해 볼 것이다.

저번에 무신사의 매거진 페이지 내용을 요약하는 기능을 구현해보았는데,

python 자체 내에서 크롤링까지 진행하면 빠른 속도와 원하는 정보만 추출하기에 유용할 것 같아 사용해보았다.

우리가 사용할 정보량은 많은 편이 아니기에 selenium, scrapy 등 다양한 웹 크롤러 도구들이 있지만

Beautifulsoup를 사용해 볼 것이다.


우선 오늘 크롤링을 진행해볼 페이지이다. (저번 요약 기능 구현에 사용되기도 했다.)

https://www.musinsa.com/cms/news/view/6112

 

키치한 스트릿 웨어 찾는다면? 유쓰배쓰 주목! | 무신사

'Youth Be At The Head’ 슬로건을 줄여 이름 지은 유쓰배쓰는 세상의 모든 청춘을 응원한다는 의미를 담은 밝은 분위기의 캐주얼 브랜드. 23 S/S 컬렉션은 ‘영 스타 스트리트’ 테마 아래 유쓰배쓰만

www.musinsa.com

필요한 라이브러리를 import해준다.

import requests
import re
from bs4 import BeautifulSoup

크롤링을 원하는 페이지의 url을 넣어주고 해당 페이지의 html 내용을 확인해본다.

#step1 : Download the webpage
url= "https://www.musinsa.com/cms/news/view/6112"
response = requests.get(url)
html_content = response.text

print(response)
print(html_content)
#step2 : Parse the HTML
soup = BeautifulSoup(html_content, 'html.parser')

이제 해당 페이지의 html에서 필요한 부분만 추출해보겠다.

먼저, 매거진의 대표 사진을 가져와보자.

# Find the div with class 'upload-Img'
div = soup.find('div', class_='upload-Img')

# Get the style attribute value
style_attr = div['style']

# Use a regular expression to extract the URL from the style attribute value
image_url_match = re.search(r'url\("(.*?)"\)', style_attr)

# Check if a match was found before trying to access the group method
if image_url_match:
    image_url = image_url_match.group(1)
    print(image_url)
else:
    print("No match found")

매거진의 대표 사진 url을 잘 가져온 것을 확인할 수 있다.

이제 매거진의 제목을 가져와보자.

#step3 : Identify the tags and attributes for the information we need

mg_title = soup.find('title').get_text()
mg_title = mg_title.split('|')[0].strip()
print(mg_title)

<title>키치한 스트릿 웨어 찾는다면? 유쓰배쓰 주목! | 무신사</title> 이 부분에서 텍스트만 가져온 후, |무신사는 제거해주었다.

다음은 매거진의 주요 내용을 알려주는 check point 부분을 가져와보자.

section = soup.find('section', class_='text-checkpoint')

# Find all list items within the section
list_items = section.find_all('li', edittype='text-align')

# Get text content from each list item
for index, li in enumerate(list_items):
    text_content = li.span.b.get_text()
    print(f"Check Point {index+1}: {text_content}")

다음은 매거진의 본문을 가져와보자.

# Find the section with class 'text-contents'
section = soup.find('section', class_='text-contents')

# Find the <p> tag within the section and get its text content
text_content = section.p.span.get_text()

# Print the extracted text content
print(text_content)

출력된 내용이 길어 첨부하지 않겠지만, 잘 가져온 것을 확인하였다.

이제 매거진 페이지에서 관련 상품 부분을 가져와 리스트로 정리해 볼 것이다.

관련 상품 목록에서 각 상품의 번호, 이미지 url, 상품 url, 브랜드, 상품명, 가격만 가져와보겠다.

goods_units = soup.find_all('li', class_='goods-unit')

for index, unit in enumerate(goods_units):
    # Get goods number
    goods_no = unit.get('goods_no')
    
    # Get image URL
    img_url = unit.find('img', class_='lazy-img').get('data-src')
    
    # Get product URL
    product_url = unit.find('div', class_='img').a.get('href')
    
    # Get brand name
    brand = unit.find('a', class_='brand').text
    
    # Get product name
    product_name = unit.find('a', class_='name').text
    
    # Get product price
    price = unit.find('span', class_='price').text
    
    print(f"Goods No: {goods_no}")
    print(f"Image URL: {img_url}")
    print(f"Product URL: {product_url}")
    print(f"Brand: {brand}")
    print(f"Product Name: {product_name}")
    print(f"Price: {price}")
    print("-" * 50)  # Separator for each product

마지막으로, 매거진의 저자와 게시일을 가져와서 한 줄로 정리해보자.

# Get the editor name from the HTML part
editor = soup.find('span', class_='opt-editable').get_text()

dates = re.findall(r'\b(?!0000\.00\.00\b)\d{4}\.\d{2}\.\d{2}\b', html_content)

# Print all found dates that are not '0000.00.00'
for date in dates:
    date

# Combine the editor name and publication date into the desired format
result = f'{editor}, 게시일 {date}'

print(result)

게시일 날짜 부분은 class로 가져오는데 한계가 있어서 html에서 날짜 형태를 찾은 다음 정리해준 것이다. (추후에 더 정확하게 구현해보겠다)

 

Beautifulsoup를 사용하여 손쉽게 웹 크롤링을 진행해보았다. 

댓글