OkBublewrap

웹 스크랩핑(2) 본문

Python/학습용

웹 스크랩핑(2)

옥뽁뽁 2023. 3. 16. 22:10

2023-03-16

예제4 

%%writefile C:/myPyCode/br_example_constitution.html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>줄 바꿈 테스트 예제</title>
  </head>
  <body>
  <p id="title"><b>대한민국헌법</b></p>
  <p id="content">제1조 <br/>①대한민국은 민주공화국이다.<br/>②대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.</p>
  <p id="content">제2조 <br/>①대한민국의 국민이 되는 요건은 법률로 정한다.<br/>②국가는 법률이 정하는 바에 의하여 재외국민을 보호할 의무를 진다.</p>
  </body>
</html>
# utf-8으로 인코딩(한글)
f = open('C:/myPyCode/br_example_constitution.html', encoding='utf-8')

html_source = f.read()
f.close()

soup = BeautifulSoup(html_source, "lxml")

# title 제목
title = soup.find('p', {"id":"title"})
# p 태그 콘텐츠 가져오기
contents = soup.find_all('p', {"id":"content"})

print(title.get_text())
for content in contents:
    print(content.get_text())

이렇게 보기 싫게 글이 나온다. 이를 정렬 하는 방법이 있다. 작성할 때 보면 글 사이에 <br/>으로 문장이 나눠진 것을 볼 수가 있다. 이부분을 띄어쓰기 '\n'으로 대체해서 사용해 정렬을 한다.

 

html1 = '<p id="content">제1조 <br/>①대한민국은 민주공화국이다.<br/>②대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.</p>'

soup1 = BeautifulSoup(html1, "lxml")

print("==> 태그 p로 찾은 요소")
content1 = soup1.find('p', {"id":"content"})
print(content1)

br_content = content1.find("br")
print("==> 결과에서 태그 br로 찾은 요소:", br_content)

br_content.replace_with("\n")
print("==> 태그 br을 개행문자로 바꾼 결과")
print(content1)
==> 태그 p로 찾은 요소
<p id="content">제1조 <br/>①대한민국은 민주공화국이다.<br/>②대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.</p>
==> 결과에서 태그 br로 찾은 요소: <br/>
==> 태그 br을 개행문자로 바꾼 결과
<p id="content">제1조 
①대한민국은 민주공화국이다.<br/>②대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.</p>
soup2 = BeautifulSoup(html1, "lxml")
content2 = soup2.find('p', {"id":"content"})

br_contents = content2.find_all("br")
for br_content in br_contents:
    br_content.replace_with("\n")
print(content2)

replace_with이 함수도 하나만 변할수 있게 할 수 있는 것 같다. 책에서는 이것을 그냥 함수로 만들어서 진행을 했다

# 줄맞춤 함수
def replace_newline(soup_html):
    br_to_newlines = soup_html.find_all("br")
    for br_to_newline in br_to_newlines: 
        br_to_newline.replace_with("\n")
    return soup_html

 

웹 스크랩핑 시 주의 사항

1. 소스코드에서 데이터를 얻기 위한 규칙을 발견할 수 있어야 한다. 

2. 사이트 접근 주기를 짧게 설정하지 않는 것이 예의! (서버의 부담)

3. 웹 사이트는 변경될 수 있기 때문에 코드를 주기적으로 변경, 관리를 해야 한다.

4. 저작권이 있는 경우가 있기 때문에 저작권 침해 여부를 미리 확인을 해야 한다.

 

웹 스크랩핑 vs 웹 크롤링

웹 스크랩핑 : 웹 사이트 내용을 가져와서 특정 데이터를 추출하는 것

웹 크롤링 : 가능한 웹 사이트 전체의 내용을 긁어와서 복제하는 것

 

순위 데이터 가져오기

아마존 알렉사의 사이트를 가지고 스크랩을 하는데 사이트 자체가 구동이 되지 않았다.

네이버 노래를 이용하기로 했다. 

https://vibe.naver.com/chart/total

 

오늘 종합 Top 100

[VIBE] 좋아하는 음악, 좋아할 음악이 모두 여기에

vibe.naver.com

2023-03-16에 순위가 3위까지 인 곡들을 가져왔다. 

1위 Ditto인 것을 보면

rank
name

요쪽으로 나온 것을 볼 수가 있다. 

전체적인 차트는

<tr class>...</tr> 하나하나가 저 메뉴바가 되는 것이다. 하지만 request 했을 때 해당부분이 안 들어간 것을 확인을 했다.

추후에 방법을 찾아서 진행을 해봐야 겠다.

 

2023-03-17

GoogleDriver을 이용해서 정보를 가져오기로 했다. 

# Packages
import requests
from bs4 import BeautifulSoup
import time
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# URL, GoogleDriver
url = "https://vibe.naver.com/chart/total"
path = 'C:\\Temp1\\chromedriver_win32\\chromedriver.exe'

driver = webdriver.Chrome(path)
driver.get(url)

# 팝업창 지우기
driver.find_element_by_xpath('//*[@id="app"]/div[2]/div/div/a[2]').click()

# 현재 페이지 html 가져오기
html = driver.page_source 
soup = BeautifulSoup(html, 'html.parser')

# song name
soup.select_one('#content > div.track_section > div:nth-child(2) > div > table > tbody > tr:nth-child(1) > td.song > div.title_badge_wrap > span > a').get_text()

# singer name
soup.select_one('#content > div.track_section > div:nth-child(2) > div > table > tbody > tr:nth-child(1) > td.artist > span > span > span > a > span').get_text()

song name : 'Ditto'

siger name : 'NewJeans'

로 잘 나온 것을 확인 할 수 있다.

 

Song name

# song 
song = []
for i in range(100):
    a = soup.select('.inner_cell')[i].text
    song.append(a)
    
song[:3]
['Ditto', 'Hype boy', '사건의 지평선']

song 부분이 잘 추출이 된 것을 볼 수 가 있다.

 

 

Singer name

똑같은 코드로 진행을 했을 때 228개가 나온 것을 볼 수 가 있다. 앞부분만 봤을 때는 두개 씩 아티스트 이름이 나온 것을 볼 수 가 있었다.

soup.select('a.link_artist')[:6]
[<a class="link_artist" href="/artist/5615371"><span class="text">NewJeans</span></a>,
 <a class="link_artist" href="/artist/5615371"><span class="text">NewJeans</span></a>,
 <a class="link_artist" href="/artist/5615371"><span class="text">NewJeans</span></a>,
 <a class="link_artist" href="/artist/5615371"><span class="text">NewJeans</span></a>,
 <a class="link_artist" href="/artist/15649"><span class="text">윤하</span></a>,
 <a class="link_artist" href="/artist/15649"><span class="text">윤하</span></a>]

1위 뉴진스, 2위 뉴진스 3위, 윤하 이렇게 나와야하는데 중복되서 나온 것을 볼 수 가 있다.

길이 수는 228개로 나는데 연결된 부분이 더 많은 것 같다. 

 

singer = []
for i in range(2,102):
    a = soup.select('.link_artist')[i].text
    song.append(a)

 

데이터 프레임 만들기

import numpy as np
import pandas as pd

data = {
    'num' : list(range(1, 101)),
    'song' : song,
    'singer' : singer
}
song_list = pd.DataFrame(data)
song_list

song_list[['singer', 'num']].groupby('singer').count().sort_values('num', ascending = False)[:10]

뉴진스와, 찰리푸스, 아이브가 순위 100위권에 제일 많은 노래를 차지 하고 있는 것을 알 수 있다. 

'Python > 학습용' 카테고리의 다른 글

웹 스크랩핑(4)  (0) 2023.03.17
웹 스크랩핑(3)  (0) 2023.03.17
웹 스크래핑(1)  (0) 2023.03.16
군집화(cluster)(3)  (0) 2022.12.12
군집화(cluster)(2)  (0) 2022.12.11