๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป IT·๊ธฐ์ˆ ·ํ†ต๊ณ„

[์›นํฌ๋กค๋ง 1ํƒ„] requests์™€ bs4๋ฅผ ํ™œ์šฉํ•œ ๋ ˆ์‹œํ”ผ ๋ชฉ๋ก ํฌ๋กค๋ง

by nowgeun 2023. 1. 19.
728x90

ํšŒ์‚ฌ์—์„œ ํ˜น์€ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ํฌ๋กค๋งํ•ด ์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ์žˆ์Šต๋‹ˆ๋‹ค. ์ œํ’ˆ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค๋˜์ง€, ์ตœ๊ทผ 2๋…„ ์น˜์˜ ๊ฒฝ์ œ ๋‰ด์Šค ๊ธฐ์‚ฌ๋ฅผ ๋ชจ์€๋‹ค๋˜์ง€ ๋“ฑ ์›น์‚ฌ์ดํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์ˆ˜์ง‘ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. 

 

์ง€๊ธˆ๊นŒ์ง€๋Š” ์ฃผ๋กœ requests์™€ bs4 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ–ˆ๊ณ , JavaScript ๋น„์ค‘์ด ๋†’์€ ๋™์  ์›น์‚ฌ์ดํŠธ๋Š” selenium์„ ํ†ตํ•ด ๋ธŒ๋ผ์šฐ์ €๋กœ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ž‘์—…์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ์—ฐํ•˜๊ฒŒ requests ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ์ž‘ํ•œ ์‚ฌ๋žŒ๋“ค์ด JavaScript์ง€์›์„ ํ•˜๋Š” requests-html์ด๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์–ด์„œ ์ด์™• ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋Š” ๊น€์— ํฌ๋กค๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•˜๋Š” ์‹œ๋ฆฌ์ฆˆ ํ˜• ํฌ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” requests์™€ bs4์„ ํ™œ์šฉํ•œ ์ •์  ์›นํŽ˜์ด์ง€๋ฅผ ํฌ๋กค๋งํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 


requests ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (+ ์ธํ„ฐ๋„ท์˜ ์ž‘๋™ ์›๋ฆฌ)

requests๋Š” python์„ ์œ„ํ•œ http ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋‹จ์ˆœํ•˜๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด ์ธํ„ฐ๋„ท์ƒ์˜ ๋ฐ์ดํ„ฐ (HTML, CSS, Javascript)๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ €์ธ ํฌ๋กฌ, ํŒŒ์ด์–ดํญ์Šค, ์—์ง€๊ฐ€ ์•„๋‹Œ python์œผ๋กœ ์ง์ ‘ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๊ทธ๋ฆผ์„ ๋ณด์‹œ๋ฉด ๋” ์‰ฝ๊ฒŒ ์ดํ•ด๋ฅผ ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

์ถœ์ฒ˜: https://timetodev.co.kr/article/index?aidx=149

 

 

ํฌ๋กฌ์˜ ๊ฒฝ์šฐ ctrl + shift + i ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ํ™”๋ฉด์œผ๋กœ ๋„˜์–ด๊ฐ€ ํ˜„์žฌ ๋ณด๊ณ  ์žˆ๋Š” ์›นํŽ˜์ด์ง€์˜ HTML, CSS, JavaScript๋ฅผ ํ™•์ธํ•ด๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ requests ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์•„๋ž˜ ์šฐ์ธก ๊ทธ๋ฆผ์— HTML์ด๋ผ๊ณ  ๋นจ๊ฐ›๊ฒŒ ํ‘œ๊ธฐ๋œ ๋ถ€๋ถ„์„ Python์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์—์„œ ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ์ •๋ณด๋งŒ HTML ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ€์ ธ์˜ค๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€ requests ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ •์  ์›นํŽ˜์ด์ง€ ํฌ๋กค๋ง์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

(์ •์  ์›น์‚ฌ์ดํŠธ vs ๋™์  ์›น์‚ฌ์ดํŠธ์— ๋Œ€ํ•œ ์„ค๋ช…์€ ๋งํฌ ์ฐธ๊ณ ํ•˜์„ธ์š”)

 

๊ทธ๋Ÿผ ์ด์ œ requests๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํฌ๋กค๋ง์„ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋งŒ๊ฐœ์˜ ๋ ˆ์‹œํ”ผ ํ™ˆํŽ˜์ด์ง€์—์„œ ์ƒ์œ„ 100๊ฐœ์˜ ๋ ˆ์‹œํ”ผ ๋ชฉ๋ก๋ฅผ ๊ฐ€์ ธ์™€๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

ํฌ๋กค๋ง ํŒ

 

1. ๊ฐœ๋ฐœ์ž ๋„๊ตฌ, ์†Œ์Šค ๊ฒ€์‚ฌ ์†์„ฑ์„ ์ž˜ ์ด์šฉํ•˜๊ธฐ

ํฌ๋กฌ์€ ctrl+shift+i ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ์ฝ˜์†”์„ ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดํ›„ ctrl + shift + c๋ฅผ ๋ˆ„๋ฅธ ๋‹ค๋ฉด, ์ปค์„œ๊ฐ€ ์˜ฌ๋ ค์ง„ ๊ณณ์˜ HTML ์ฝ”๋“œ ๋ถ€๋ถ„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜น์€ ๋‹จ์ˆœํ•˜๊ฒŒ ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ์„ ํ•˜์—ฌ ๊ฒ€์‚ฌ๋ฅผ ๋ˆ„๋ฅด๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

2. ์ˆ˜์ง‘ํ•˜๊ณ  ์‹ถ์€ ์ •๋ณด๊ฐ€ ์–ด๋–ค ๊ตฌ์กฐ๋กœ ๋˜์–ด์žˆ๋Š”์ง€ ํŒŒ์•…ํ•˜๊ธฐ

์•„๋ž˜์˜ ์‚ฌ์ง„์„ ๋ณด์‹œ๋ฉด, ๊ฐ๊ฐ์˜ ๋ ˆ์‹œํ”ผ๋Š” <li class='common_sp_list_li'> ๋ผ๋Š” ํƒœ๊ทธ์˜ ๋ชฉ๋ก์œผ๋กœ ์ •๋ณด๊ฐ€ ๋‚˜์—ด๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ ˆ์‹œํ”ผ ํƒœ๊ทธ๋“ค์€  <ul class='common_sp_list_ul ea4'>์ด๋ผ๋Š” ์ƒ์œ„ ํƒœ๊ทธ๊ฐ€ ์žˆ๊ณ  ๊ทธ ์œ„์—๋Š” <div class='rcp_m_list2'>๋ผ๋Š” ์ƒ์œ„ ํƒœ๊ทธ ์•„๋ž˜์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ์ •๋ณด ์™ธ์˜ ๋‹ค๋ฅธ ์ •๋ณด๋“ค์ด <li class='common_sp_list_li'> ๋ผ๋Š” ํƒœ๊ทธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ์ƒ์œ„ ํƒœ๊ทธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ ˆ์‹œํ”ผ๊ฐ€ ์œ„์น˜ํ•œ HTML์„ ํŒŒ์‹ฑ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

 

3. ์—†์„ ์ˆ˜๋„ ์žˆ๋Š” ์ •๋ณด๋Š” ์˜ˆ์™ธ์ฒ˜๋ฆฌํ•˜๊ธฐ

๋‹ค๋ฅธ ๋ ˆ์‹œํ”ผ ํ•ญ๋ชฉ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ 16์œ„ ๋ ˆ์‹œํ”ผ๋Š” ๋ฆฌ๋ทฐ ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ์—†์ด ๋ฐ˜๋ณต๋ฌธ์„ ์งฐ๋‹ค๋ฉด ์—๋Ÿฌ๊ฐ€ ์ƒ๊ธธ ํ™•๋ฅ ์ด ๋†’์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํฌ๋กค๋ง์„ ํ•˜์‹ค ๋•Œ๋Š” ์—†์„ ์ˆ˜๋„ ์žˆ๋Š” ์ •๋ณด๋ฅผ ์˜ˆ์™ธ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด ๋‘์…”์•ผ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋•Œ ํ—ˆํˆฌ๋ฃจ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ•˜๋Š” ๊ฒƒ์„ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  

 

 

์†Œ์Šค์ฝ”๋“œ

 

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณต๋ถ™ํ•˜์‹œ๋ฉด ๋ ˆ์‹œํ”ผ ๋žญํ‚น ํ™”๋ฉด์— ๋‹ด๊ธด 100๊ฐœ์˜ ๋ ˆ์‹œํ”ผ์— ๋Œ€ํ•œ ์ด๋ฆ„, ๋งํฌ, ์กฐํšŒ์ˆ˜, ๋ฆฌ๋ทฐ ๋“ฑ์˜ ์ •๋ณด๊ฐ€ ์ •๋ฆฌ๋œ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ๋ฆฌ ๊ณผ์ •๊ณผ ์žฌ๋ฃŒ์™€ ๊ฐ™์€ ์„ธ๋ถ€ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, ๋งํฌ ๋ณ„๋กœ ์ ‘์†์„ ํ•œ ๋’ค ์œ ์‚ฌํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ HTML ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

(๋งŒ์•ฝ ๊ฐ URL ๋ณ„๋กœ ๋ ˆ์‹œํ”ผ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์–ด๋ ค์›€์ด ์žˆ์œผ์‹œ๋‹ค๋ฉด, ๋Œ“๊ธ€๋กœ ๋ฌธ์˜ ์ฃผ์„ธ์š”~)

import requests
import pandas as pd
from bs4 import BeautifulSoup

# URL ์ž…๋ ฅ (ํฌ๋กค๋ง ๋Œ€์ƒ ์›น์‚ฌ์ดํŠธ) 
url = 'https://www.10000recipe.com/ranking/home_new.html'  

# HTTPS ํ˜ธ์ถœ
req = requests.get(url) 

# HTML ์ €์žฅ
html = req.text

# HTML ํŒŒ์‹ฑ 
soup = BeautifulSoup(html, 'html.parser')

# ๋ ˆ์‹œํ”ผ ๋ชฉ๋ก์ด ๋‹ด๊ธด HTML ํƒœ๊ทธ
recipes = soup.find_all('li', {"class":"common_sp_list_li"})

# ๋ ˆ์‹œํ”ผ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋นˆ ๋ฆฌ์ŠคํŠธ
recipe_data = []

# ๊ฐ ๋ ˆ์‹œํ”ผ์˜ ํƒœ๊ทธ ๋‚ด ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ HTML ํƒœ๊ทธ๋กœ ์ฐพ์•„์„œ ๋ณ€์ˆ˜๋กœ ์ €์žฅ
for recipe in recipes:
    recipe_rank = recipe.find('p',{'class':'ranking_num'}).text
    recipe_name = recipe.find('div',{'class':'common_sp_caption_tit'}).text
    recipe_auth = recipe.find('div',{'class':'common_sp_caption_rv_name'}).text.strip()
    recipe_link = 'https://www.10000recipe.com' + recipe.find('div',{'class':'common_sp_thumb'}).find('a')['href']
    
    try: #๋ ˆ์‹œํ”ผ ๋ฆฌ๋ทฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด try, except๋กœ ๋‹จ์ˆœ ์˜ˆ์™ธ์ฒ˜๋ฆฌ
        recipe_review_num = recipe.find('span',{'class':'common_sp_caption_rv_ea'}).text.replace('(','').replace(')','')
    except:
        recipe_review_num = '0'
        
    recipe_view_cnt = recipe.find('span',{'class':'common_sp_caption_buyer'}).text.replace('์กฐํšŒ์ˆ˜ ','')
	
    # ๋นˆ ๋ฆฌ์ŠคํŠธ์— ๋ฐ์ดํ„ฐ ์ €์žฅ
    recipe_data.append([recipe_rank, recipe_name, recipe_auth, recipe_link, recipe_review_num, recipe_view_cnt])


# Pandas DataFrame์œผ๋กœ ์ €์žฅ
df = pd.DataFrame(recipe_data, columns=['๋žญํ‚น','๋ ˆ์‹œํ”ผ์ œ๋ชฉ','์ž‘์„ฑ์ž','๋ ˆ์‹œํ”ผ๋งํฌ','๋ฆฌ๋ทฐ์ˆ˜','์กฐํšŒ์ˆ˜'])

# ๋žญํ‚น ๋ฐ์ดํ„ฐ csv ํŒŒ์ผ๋กœ ์ €์žฅ (์—‘์…€๋กœ ๋‚˜์ค‘์— ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๊ฐ€๋Šฅ)
df.to_csv('๋งŒ๊ฐœ์˜๋ ˆ์‹œํ”ผ_Top_100.csv', encoding='cp949')

# ์ฒซ 5๊ฐœ์˜ ํ–‰๋งŒ ๊ฐ€์ ธ์˜ค๊ธฐ
df.head()

 

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€