안녕하세요. 카일입니다.
yes24 부동산/경매 카테고리에 있는 도서 중에서 실시간 베스트 도서 목록을 가져오는 작업을 시도해보았습니다.
먼저 도서정보를 크롤링하기 위한 준비작업이 무엇이 필요한지 물어봤습니다.
부동산/경매 실시간 베스트 카테고리 페이지의 URL 을 알려주고 코드 작성을 요청했습니다.
해당 코드로 실행을 해보니 오류가 발생하였습니다. 오류 코드를 입력 후 다시 요청하였습니다.
비슷한 유형의 오류가 발생하였습니다. 그래서 크롤링할 데이터 항목의 식별자를 직접 찾아서 입력 후 다시 요청하였습니다.
콘솔에 정상적으로 출력이 되는 것을 확인하고 도서 url 정보를 추가로 요청하였습니다.
추가 요청 정보도 정상 출력되는 것을 확인하고 해당 코드를 옵시디언에서 실행하기 위해 quickadd에서 사용가능한 스트립트로 만들어 달라고 요청하였습니다.
옵시디언에서 스크립트를 실행하니 작동이 안되어 콘솔의 오류 메시지를 입력하였습니다.
옵시디언에서 직접 파일 생성은 CORS 문제로 다른 해결책을 제시하였습니다. 다른 방식은 md 파일을 로컬 폴더에 생성한 후 옵시디언 폴더로 옮기는 것입니다.
md파일을 확인 한 후 실시간 기준 정보 추가를 요청하였습니다.
마지막으로 옵시디언에서 해당 노트를 확인하였습니다.
결론
download_path 는 로컬 저장 경로를 입력합니다.
url을 변경하면 해당 url 페이지의 도서목록을 크롤링 할 수 있습니다.
range값을 변경하면 해당 순위까지의 도서목록을 md파일로 만들 수 있습니다.
아래는 코드 전문입니다.
import requests
from bs4 import BeautifulSoup
from datetime import datetime
import os
def fetch_book_info():
url = "https://www.yes24.com/Product/Category/RealTimeBestSeller?categoryNumber=001001025010003" # 부동산/경매 실시간 베스트 url입니다.
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# 실시간 기준 정보 추출
realtime_criteria_selector = '#spnBaseFilter > span'
realtime_criteria = soup.select_one(realtime_criteria_selector).get_text(strip=True)
books = []
for index in range(1, 5): # 1-5순위 도서만 출력합니다.
title_selector = f'#yesBestList > li:nth-child({index}) > div > div.item_info > div.info_row.info_name > a.gd_name'
image_selector = f'#yesBestList > li:nth-child({index}) > div > div.item_img > div.img_canvas > span > span > a > em > img'
author_selector = f'#yesBestList > li:nth-child({index}) > div > div.item_info > div.info_row.info_pubGrp > span.authPub.info_auth > a'
publisher_selector = f'#yesBestList > li:nth-child({index}) > div > div.item_info > div.info_row.info_pubGrp > span.authPub.info_pub > a'
pub_date_selector = f'#yesBestList > li:nth-child({index}) > div > div.item_info > div.info_row.info_pubGrp > span.authPub.info_date'
sale_num_selector = f'#yesBestList > li:nth-child({index}) > div > div.item_info > div.info_row.info_rating > span.saleNum'
url_selector = f'#yesBestList > li:nth-child({index}) > div > div.item_info > div.info_row.info_name > a.gd_name'
title = soup.select_one(title_selector).get_text(strip=True)
image_element = soup.select_one(image_selector)
image_url = image_element.get('src') if image_element else '이미지 없음'
author = soup.select_one(author_selector).get_text(strip=True)
publisher = soup.select_one(publisher_selector).get_text(strip=True)
pub_date = soup.select_one(pub_date_selector).get_text(strip=True)
sale_num = soup.select_one(sale_num_selector).get_text(strip=True)
book_url = soup.select_one(url_selector).get('href')
books.append({
"rank": index,
"title": title,
"author": author,
"publisher": publisher,
"pub_date": pub_date,
"sale_num": sale_num,
"image_url": image_url,
"book_url": f"https://www.yes24.com{book_url}",
"realtime_criteria": realtime_criteria
})
return books
def generate_markdown(book):
current_date = datetime.now().strftime("%Y-%m-%d %H:%M")
frontmatter = f"""---
created: {current_date}
rank: {book['rank']}
tag: 도서정보
title: {book['title']}
author: {book['author']}
publisher: {book['publisher']}
pub_date: {book['pub_date']}
sale_num: {book['sale_num']}
image_url: {book['image_url']}
book_url: {book['book_url']}
realtime_criteria: {book['realtime_criteria']}
---
"""
content = f"""
## YES24 부동산/경매 실시간 베스트 도서 목록
### {book['title']}
- 저자명: {book['author']}
- 출판사: {book['publisher']}
- 출간일: {book['pub_date']}
- 판매지수: {book['sale_num']}
- 이미지 URL: {book['image_url']}
- 도서 URL: {book['book_url']}
"""
return frontmatter + content
def main():
books = fetch_book_info()
download_path = "/Users/Downloads" # 로컬 저장 경로를 입력하세요
if not os.path.exists(download_path):
print(f"Directory {download_path} does not exist.")
return
for book in books:
markdown = generate_markdown(book)
file_name = f"{book['title'].replace('/', '_')}.md"
file_path = os.path.join(download_path, file_name)
with open(file_path, 'w', encoding='utf-8') as f:
f.write(markdown)
print(f"Created file: {file_path}")
if __name__ == "__main__":
main()
#11기 내집마련