๐Ÿ“ฆ๋ถ„์„ ํ”„๋กœ์ ํŠธ/๐Ÿš… ํฌ๋กค๋ง ๋ถ„์„

๐Ÿš… ํฌ๋กค๋ง ๋ถ„์„ ํ”„๋กœ์ ํŠธ (2) - Selenium ํ™œ์šฉ ๋‰ด์Šค ํฌ๋กค๋ง

๋ฐ์ดํ„ฐํŒ์Šค 2024. 10. 17. 16:20

์—ฌ๋Ÿฌ ํŽ˜์ด์ง€ ํฌ๋กค๋ง ํ•˜๊ธฐ

์™ผ์ชฝ ๋‰ด์ŠคํŽ˜์ด์ง€ ๋ฐ•์Šค ๋ถ€๋ถ„์€ ์˜ค๋ฅธ์ชฝ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ €๋Š” ์—ฌ๊ธฐ์„œ a ํƒœ๊ทธ๋ฅผ ๊ฐ€์ง„,  ๊ฐ ๋ฐ•์Šค์— ํ•ด๋‹น ๋˜๋Š” ๋‚ด์šฉ๋“ค์„ ๊ฐ€์ ธ์˜ค๋ ค ํ•ฉ๋‹ˆ๋‹ค.

 

 

url='https://news.kbs.co.kr/news/pc/category/category.do?ref=pSiteMap#20241017&1'
html_doc=requests.get(url).text
html_doc

soup=BeautifulSoup(html_doc,'html.parser')
soup

# ๋ฐ•์Šค์—์„œ ํƒœ๊ทธ์ด๋ฆ„์ด a์ธ๊ฑธ ๋ชจ๋‘ ์ฐพ์•„์„œ ๋ฐ•์Šค ์ปจํ…์ธ  ๋ผ๋Š” ๋ณ€์ˆ˜์— ๋‹ด์Œ
box_contents=soup.find_all('a',class_='box-content flex-style')
box_contents

์ด์ „ ๊ฒŒ์‹œ๊ธ€์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ๋ฒ•๋Œ€๋กœ BeautifulSoup ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

ํ•˜์ง€๋งŒ ํŽ˜์ด์ง€๊ฐ€ ๋‹ด๊ฒจ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋‚ด์šฉ์€ BeautifulSoup ๊ธฐ๋Šฅ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ Selenium์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

 

 

 

Selenium์ด๋ž€?

๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ด๊ฒจ์ ธ ์žˆ์ง€ ์•Š์€ ์›์ธ

1. ํฌ๋กค๋ง ํ•˜๋ ค๋Š” ํƒœ๊ทธ๋“ค์ด ์ž˜ ์„ฑ์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค

2. ํŽ˜์ด์ง€ ์†Œ์Šค์— javascript๊ฐ€ ์‚ฌ์šฉ ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - ๋งŽ์€ ์›นํŽ˜์ด์ง€๋“ค์ด javascript ๋™์  ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œ

ํŽ˜์ด์ง€์— ๋จผ์ € ์ ‘๊ทผ ํ•œ ์ดํ›„์— ๋™์ ์œผ๋กœ javascript๋ฅผ ํ™œ์šฉํ•ด ์ปจํ…์ธ ๋“ค์ด ์ƒ์„ฑ๋œ๋‹ค๋ฉด  ๊ฐ€์ ธ์˜ฌ ์ˆ˜๊ฐ€์—†๋‹ค

 

์ด ๊ฒฝ์šฐ, ํ•ด๊ฒฐ์ฑ… = Selenium

Selenium ์›น ํŽ˜์ด์ง€๋ฅผ ์ž๋™์œผ๋กœ ์ œ์–ด, ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ

์ง์ ‘์ ์œผ๋กœ ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ œ์–ดํ•œ๋‹ค

Request, BeautifulSoup์œผ๋กœ ํฌ๋กค๋ง์ด ๋ถˆ๊ฐ€๋Šฅ ํ•  ๋•Œ, ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ๋ชปํ•  ๊ฒฝ์šฐ Selenium ์‚ฌ์šฉ

 

์ •์  ํŽ˜์ด์ง€ = Requests + Beautiful Soup

  • ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ํ•œ ๋ฒˆ ์š”์ฒญํ•˜๋ฉด ๋ณ€ํ•˜์ง€ ์•Š๋Š” ํ˜•ํƒœ์˜ html๋กœ ์ž‘์„ฑ๋œ ํŽ˜์ด์ง€
  • ์›น ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ๋•Œ ๋งˆ๋‹ค ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋†“์€ html ํŒŒ์ผ์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค
  • ์„œ๋ฒ„ ์ธก์—์„œ ๋ฏธ๋ฆฌ ์ค€๋น„๊ฐ€ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๋ณ„๋‹ค๋ฅธ ์ฒ˜๋ฆฌ ์—†์ด ๋ฐ”๋กœ ๋ธŒ๋ผ์šฐ์ €์— ํ‘œ์‹œ

 

๋™์  ํŽ˜์ด์ง€ =  Selenium

  • ์›น ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ html์„ ๋ฐ›์•„์˜จ ๋‹ค์Œ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด์„ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋ฉด์„œ javascript ๊ฐ™์€ ์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ ์œผ๋กœ ์›นํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ ๋‹ค
  • ์ด๋ ‡๊ฒŒ ํ˜•์„ฑ๋œ html ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ์ž…๋ ฅ, ํด๋ฆญ,์Šคํฌ๋กค ํ•  ๋•Œ ํ™”๋ฉด์ด ๋ณ€๊ฒฝ๋˜๋Š” ๋“ฑ์˜ ์ƒํ˜ธ ์ž‘์šฉ์ด ํ•„์š”ํ•œ ์›นํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉ

 

 

 

Selenium์„ ํ™œ์šฉํ•˜์—ฌ ๋‰ด์Šค ํฌ๋กค๋ง

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait

# selenium์œผ๋กœ ์›น๋“œ๋ผ์ด๋ฒ„ ์‹คํ–‰

service=Service(executable_path=ChromeDriverManager().install())
# ํฌ๋กฌ ์›น ๋“œ๋ผ์ด๋ฒ„๊ฐ€ ์–ด๋””์— ์œ„์น˜ํ•ด ์žˆ๋‹ค๋Š” ์•Œ๋ ค์ฃผ๋Š” ๊ฒฝ๋กœ ์ž๋ฆฌ์— ํฌ๋กฌ๋“œ๋ผ์ด๋ฒ„ ๋งค๋‹ˆ์ € ์„ค์น˜ํ•œ ๊ฐ’์„ ๋„ฃ๊ธฐ
driver = webdriver.Chrome(service=service)

#url ์ „๋‹ฌ
url='https://news.kbs.co.kr/news/pc/category/category.do?ref=pSiteMap#20241017&1'
driver.get(url)

# ๊ธฐ๋‹ค๋ ค๋‹ฌ๋ผ๋Š” ๊ฐ’์„ ์ „๋‹ฌ : ์ตœ๋Œ€ 10์ดˆ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ
wait=WebDriverWait(driver,10)

# ๋“œ๋ผ์ด๋ฒ„ ์ ‘๊ทผ > ํŽ˜์ด์ง€ ์†Œ์Šค ๊ฐ€์ ธ์˜ค๊ธฐ
html=driver.page_source

#๋“œ๋ผ์ด๋ฒ„ ์ข…๋ฃŒ
driver.quit()

๋“œ๋ผ์ด๋ฒ„๋ฅผ ์ข…๋ฃŒํ•˜์ง€ ์•Š์œผ๋ฉด ๊ณ„์† ์‹คํ–‰๋˜๋‹ˆ ๊ผญ ์ข…๋ฃŒ ์ฝ”๋“œ๋ฅผ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

soup=BeautifulSoup(html,'html.parser')

box_contents=soup.find_all('a',class_='box-content flex-style')
box_contents

์ด๋ฒˆ์—๋Š” ์›ํ•˜๋Š” ๋‚ด์šฉ์ด ์ œ๋Œ€๋กœ ๋‹ด๊ฒผ์Šต๋‹ˆ๋‹ค.

 

 

 

 

์›ํ•˜๋Š” ์ •๋ณด๋งŒ ๊ฐ€์ ธ์˜ค๊ธฐ

https://news.kbs.co.kr/news/pc/view/view.do?ncd=8083891

 

BBC “๋Ÿฌ ๊ทน๋™ ๊ตฐ์‚ฌ๊ธฐ์ง€์— ๋ถํ•œ์ธ ๋„์ฐฉ…์ธ์›์€ ํ™•์ธ ๋ชปํ•ด”

์ ค๋ Œ์Šคํ‚ค ์šฐํฌ๋ผ์ด๋‚˜ ๋Œ€ํ†ต๋ น์ด ๋ถํ•œ์˜ ๋Ÿฌ์‹œ์•„ ํŒŒ๋ณ‘์„ ํ™•์ธํ–ˆ๋‹ค๊ณ  ์ฃผ์žฅํ•˜๋Š” ๊ฐ€์šด๋ฐ ์˜๊ตญ BBC ๋ฐฉ์†ก์ด ํ˜„์ง€ ์ทจ...

news.kbs.co.kr

ํ•ด๋‹น ๊ธฐ์‚ฌ๋Š”https://news.kbs.co.kr + /news/pc/view/view.do?ncd=808391๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

url="http://news.kbs.co.kr" + box_contents[0]['href']
url

 

๋ฐ•์Šค ์ปจํ…์ธ ์—์„œ ๊ฐ€์žฅ ์ฒซ๋ฒˆ์งธ ๊ธฐ์‚ฌ๋ฅผ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ href์„ ํƒํ•˜๋ฉด url์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

# ํƒ€์ดํ‹€ ์ถœ๋ ฅ
title=box_contents[0].find('p',class_='title').text
title

# ๋ณธ๋ฌธ ์ถœ๋ ฅ
body=box_contents[0].find('p',class_='news-text').text
body

# ๋‚ ์งœ ์ถœ๋ ฅ
date=box_contents[0].find('span',class_='date').text
date

์ด๋Ÿฐ์‹์œผ๋กœ ์›ํ•˜๋Š” ๊ธฐ์‚ฌ๋งŒ ์„ ํƒํ•ด์„œ ์ œ๋ชฉ,๋ณธ๋ฌธ,๋‚ ์งœ๋ฅผ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

for๋ฌธ์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ ์ถ”์ถœ

# ์›ํ•˜๋Š” ๋ถ€๋ถ„๋“ค๋งŒ ์ฐพ์•„์„œ, ๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ณ , ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„์œผ๋กœ ๋งŒ๋“ค๊ธฐ
# ๋นˆ ๋ฆฌ์ŠคํŠธ ๋งŒ๋“ค๊ธฐ
url_list=[]
title_list=[]
body_list=[]
date_list=[]

for box_content in box_contents:
    url = "http://news.kbs.co.kr" + box_content['href']
    title = box_content.find('p',class_='title').text
    body = box_content.find('p',class_='news-text').text
    date = box_content.find('span',class_='date').text
    
    url_list.append(url)
    title_list.append(title)
    body_list.append(body)
    date_list.append(date)

box_contents์—๋Š” 12๊ฐœ์˜ ๋‚ด์šฉ์ด ๋‹ด๊ธด ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

๊ทธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋Œ๋ฉด์„œ ๋‚ด์šฉ๋“ค์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

 

# ๋ฐ์ดํ„ฐ ์ €์žฅ
data={'๋‰ด์Šคurl':url_list,'์ œ๋ชฉ':title_list,'๋‚ด์šฉ':body_list,'๋‚ ์งœ':date_list}
df=pd.DataFrame(data)
df

์ œ๋Œ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.

 

 

 

ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ํ™œ์šฉํ•ด ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€ ํฌ๋กค๋ง

1ํŽ˜์ด์ง€๋งŒ์ด ์•„๋‹ˆ๋ผ 1~13ํŽ˜์ด์ง€๋ฅผ ๋Œ๋ฉด์„œ ํฌ๋กค๋ง์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

# ๋นˆ ๋ฆฌ์ŠคํŠธ ๋งŒ๋“ค๊ธฐ
url_list=[]
title_list=[]
body_list=[]
date_list=[]

#์„œ๋น„์Šค ๋ณ€์ˆ˜ ์„ค์ •
service=Service(executable_path=ChromeDriverManager().install())

#1. ํŽ˜์ด์ง€๋ฅผ ๋Œ๋ฉด์„œ ์ž‘์—…์„ ์ˆ˜ํ–‰
for page_num in range(1,14):

    #Selenium์œผ๋กœ ์›น ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์‹คํ–‰
    driver = webdriver.Chrome(service=service)

    #url ์ „๋‹ฌ
    url=f'https://news.kbs.co.kr/news/pc/category/category.do?ref=pSiteMap#20241017&{page_num}'
    driver.get(url)

    # ๊ธฐ๋‹ค๋ ค๋‹ฌ๋ผ๋Š” ๊ฐ’์„ ์ „๋‹ฌ : ์ตœ๋Œ€ 10์ดˆ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ
    wait=WebDriverWait(driver,10)

    # ๋“œ๋ผ์ด๋ฒ„ ์ ‘๊ทผ > ํŽ˜์ด์ง€ ์†Œ์Šค ๊ฐ€์ ธ์˜ค๊ธฐ
    html=driver.page_source

    #๋“œ๋ผ์ด๋ฒ„ ์ข…๋ฃŒ
    driver.quit()
    
    #2. BeautifulSoup ์‚ฌ์šฉํ•ด์„œ ํŒŒ์‹ฑํ•˜๊ณ , ํƒœ๊ทธ๋ฅผ ์ฐพ์•„์„œ ๋‹ด์•„์คŒ
    soup=BeautifulSoup(html,'html.parser')
    box_contents=soup.find_all('a',class_='box-content flex-style')

    #3. ๋ฐ•์Šค ๋ฐ์ดํ„ฐ๋“ค์„ ํ•˜๋‚˜์”ฉ ๋Œ๋ฉด์„œ ๋ฆฌ์ŠคํŠธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์Œ

    for box_content in box_contents:
        url = "http://news.kbs.co.kr" + box_content['href']
        title = box_content.find('p',class_='title').text
        body = box_content.find('p',class_='news-text').text
        date = box_content.find('span',class_='date').text
        
        url_list.append(url)
        title_list.append(title)
        body_list.append(body)
        date_list.append(date)



#4. ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„์œผ๋กœ ๋ฐ์ดํ„ฐ ์ €์žฅ
data={'๋‰ด์Šคurl':url_list,'์ œ๋ชฉ':title_list,'๋‚ด์šฉ':body_list,'๋‚ ์งœ':date_list}
df=pd.DataFrame(data)
df

1~13 ํŽ˜์ด์ง€์˜ ๋‰ด์Šค๋“ค์ด ๋ชจ๋‘ ํฌ๋กค๋ง ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.