Python package를 사용한 웹 크롤링 기초

ybear90·2020년 2월 11일
0

Python

목록 보기
7/8

웹 크롤링(Crawling)은 웹 사이트에서 특정 키워드로 탐색하여 자료를 수집하는 행위를 뜻한다. 파이썬 어느정도 사용해 봤다면 몇가지 패키지들을 통해 쉽게 웹 크롤링 작업을 진행해 볼 수 있다.

준비물

python이 설치 된 개발환경(가상환경), pip 패키지 중 requests, beautifulsoup(bs4)

환경 설정

# conda 가상환경에서 작업함(venv, virtualenv 모두 상관 없다고 봄), 굳이 가상환경이 아니라도 파이썬이 설치되었으며 pip 사용 가능한 환경이면 시작 가능
$ conda create -n <env-name> python=3.8
$ source activate <env-name>
(env-name) $ pip install requests beautifulsoup4 

실제 크롤링

다음 사이트(빌보드 hot-100)를 크롤링 해서 순위, 노래제목, 가수명을 크롤링 해서 출력해보자

import requests
from bs4 import BeautifulSoup

req = requests.get('https://www.billboard.com/charts/hot-100')

html = req.text

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

위의 코드를 살펴보면 requests 모듈의 get() 함수를 이용하여 해당 웹페이지의 데이터를 Response 객체로 담아오게 되고 이 객체에서 text 파일을 열어보게 되면 html raw data가 들어 있는 것을 확인할 수 있다. 받아온 text 형태의 데이터를 BeautifulSoup객체를 생성하여 넣게 되면 beautifulsoup의 역할은 parser(분석기)로서 전체 데이터에서 html tag, CSS selector등을 이용하여 필요한 데이터를 찾게 도와준다.

rank = soup.select(
    'li > button > span.chart-element__rank.flex--column.flex--xy-center.flex--no-shrink > span.chart-element__rank__number'
)
song = soup.select(
    'li > button > span.chart-element__information > span.chart-element__information__song.text--truncate.color--primary'
)
singer = soup.select(
    'li > button > span.chart-element__information > span.chart-element__information__artist.text--truncate.color--secondary'
)

music_chart = []
# 만일 크롤링한 데이터의 갯수가 다르다면 zip_logest를 이용하여 default값을 넣어 갯수를 맞춰서 한번에 넣기도 가능
for item in zip(rank, song, singer):
    music_chart.append(
        {
            'rank' : item[0].text,
            'song' : item[1].text,
            'singer' : item[2].text
        }
    )

for element in music_chart:
    print(element)

soup 파서는 select()메소드를 통해 html 텍스트에서 필요한 부분을 찾게 되는데 앞서 말했던 것 처럼 저런 식의 selector를통해 찾게 된다 그렇다면 그 복잡한 selector를 최상위 부모요소로 부터 하나씩 확인 하는 것인가 ? 그렇지 않다. 웹 브라우저의 개발자 도구를 통하여 얻고자 하는 요소를 선택하면 해당 부분의 요소까지 단번에 갈 수 있는데 (크롬기준) 마우스 우클릭을 하면 CSS selector를 copy할 수 있게 되어 있고 이를 이용하면 된다

그렇게 요소를 찾아내면 아래와 같은 selector가 복사되고 정리하면

rank = soup.select(
    "#charts > div > div.chart-list.container > ol > li:nth-child(1) > button > span.chart-element__rank.flex--column.flex--xy-center.flex--no-shrink > span.chart-element__rank__number"
)
rank = soup.select(
    "li > button > span.chart-element__rank.flex--column.flex--xy-center.flex--no-shrink > span.chart-element__rank__number"
)

위와 같은 코드를 얻을 수 있다.

그래서 크롤링한 결과를 확인해보면 아래와 같이 나온다.

{'rank': '1', 'song': 'The Box', 'singer': 'Roddy Ricch'}
{'rank': '2', 'song': 'Life Is Good', 'singer': 'Future Featuring Drake'}
{'rank': '3', 'song': 'Circles', 'singer': 'Post Malone'}
{'rank': '4', 'song': 'Memories', 'singer': 'Maroon 5'}
{'rank': '5', 'song': 'Someone You Loved', 'singer': 'Lewis Capaldi'}
{'rank': '6', 'song': '10,000 Hours', 'singer': 'Dan + Shay & Justin Bieber'}
{'rank': '7', 'song': 'Dance Monkey', 'singer': 'Tones And I'}
{'rank': '8', 'song': 'Roxanne', 'singer': 'Arizona Zervas'}
{'rank': '9', 'song': "Don't Start Now", 'singer': 'Dua Lipa'}
{'rank': '10', 'song': 'everything i wanted', 'singer': 'Billie Eilish'}
{'rank': '11', 'song': 'Lose You To Love Me', 'singer': 'Selena Gomez'}
{'rank': '12', 'song': 'Godzilla', 'singer': 'Eminem Featuring Juice WRLD'}
{'rank': '13', 'song': 'Good As Hell', 'singer': 'Lizzo'}
{'rank': '14', 'song': 'BOP', 'singer': 'DaBaby'}
{'rank': '15', 'song': 'Yummy', 'singer': 'Justin Bieber'}
{'rank': '16', 'song': "Ballin'", 'singer': 'Mustard & Roddy Ricch'}
{'rank': '17', 'song': 'Bad Guy', 'singer': 'Billie Eilish'}
{'rank': '18', 'song': 'Blinding Lights', 'singer': 'The Weeknd'}
{'rank': '19', 'song': 'Heartless', 'singer': 'The Weeknd'}
{'rank': '20', 'song': 'HIGHEST IN THE ROOM', 'singer': 'Travis Scott'}
{'rank': '21', 'song': 'The Bones', 'singer': 'Maren Morris'}
{'rank': '22', 'song': 'High Fashion', 'singer': 'Roddy Ricch Featuring Mustard'}
{'rank': '23', 'song': 'Hot Girl Bummer', 'singer': 'blackbear'}
{'rank': '24', 'song': 'No Guidance', 'singer': 'Chris Brown Featuring Drake'}
{'rank': '25', 'song': 'Woah', 'singer': 'Lil Baby'}
{'rank': '26', 'song': 'Senorita', 'singer': 'Shawn Mendes & Camila Cabello'}
{'rank': '27', 'song': 'Trampoline', 'singer': 'SHAED'}
{'rank': '28', 'song': 'You should be sad', 'singer': 'Halsey'}
{'rank': '29', 'song': 'Adore You', 'singer': 'Harry Styles'}
{'rank': '30', 'song': 'What A Man Gotta Do', 'singer': 'Jonas Brothers'}
{'rank': '31', 'song': 'B.I.T.C.H.', 'singer': 'Megan Thee Stallion'}
{'rank': '32', 'song': 'Truth Hurts', 'singer': 'Lizzo'}
{'rank': '33', 'song': 'Falling', 'singer': 'Trevor Daniel'}
{'rank': '34', 'song': 'Anyone', 'singer': 'Demi Lovato'}
{'rank': '35', 'song': 'My Oh My', 'singer': 'Camila Cabello Featuring DaBaby'}
{'rank': '36', 'song': 'Suicidal', 'singer': 'YNW Melly'}
{'rank': '37', 'song': 'Only Human', 'singer': 'Jonas Brothers'}
{'rank': '38', 'song': 'Sum 2 Prove', 'singer': 'Lil Baby'}
{'rank': '39', 'song': 'Sucker', 'singer': 'Jonas Brothers'}
{'rank': '40', 'song': 'One Man Band', 'singer': 'Old Dominion'}
{'rank': '41', 'song': "Even Though I'm Leaving", 'singer': 'Luke Combs'}
{'rank': '42', 'song': 'Heartache Medication', 'singer': 'Jon Pardi'}
{'rank': '43', 'song': 'Nobody But You', 'singer': 'Blake Shelton Duet With Gwen Stefani'}
{'rank': '44', 'song': "I Don't Care", 'singer': 'Ed Sheeran & Justin Bieber'}
{'rank': '45', 'song': 'Hot', 'singer': 'Young Thug Featuring Gunna'}
{'rank': '46', 'song': 'Kinfolks', 'singer': 'Sam Hunt'}
{'rank': '47', 'song': 'Bandit', 'singer': 'Juice WRLD & YoungBoy Never Broke Again'}
{'rank': '48', 'song': 'Juicy', 'singer': 'Doja Cat & Tyga'}
{'rank': '49', 'song': 'Panini', 'singer': 'Lil Nas X'}
{'rank': '50', 'song': 'South Of The Border', 'singer': 'Ed Sheeran Featuring Camila Cabello & Cardi B'}
{'rank': '51', 'song': 'Tusa', 'singer': 'Karol G & Nicki Minaj'}
{'rank': '52', 'song': 'Homesick', 'singer': 'Kane Brown'}
{'rank': '53', 'song': 'RITMO (Bad Boys For Life)', 'singer': 'The Black Eyed Peas X J Balvin'}
{'rank': '54', 'song': 'Good News', 'singer': 'Mac Miller'}
{'rank': '55', 'song': 'P*$$y Fairy (OTW)', 'singer': 'Jhene Aiko'}
{'rank': '56', 'song': 'I Hope', 'singer': 'Gabby Barrett'}
{'rank': '57', 'song': 'Slide', 'singer': 'H.E.R. Featuring YG'}
{'rank': '58', 'song': 'TOES', 'singer': 'DaBaby Featuring Lil Baby & Moneybagg Yo'}
{'rank': '59', 'song': 'Heart On Ice', 'singer': 'Rod Wave'}
{'rank': '60', 'song': 'Futsal Shuffle 2020', 'singer': 'Lil Uzi Vert'}
{'rank': '61', 'song': 'VIBEZ', 'singer': 'DaBaby'}
{'rank': '62', 'song': 'BEST ON EARTH', 'singer': 'Russ & BIA'}
{'rank': '63', 'song': 'OUT WEST', 'singer': 'JACKBOYS Featuring Young Thug'}
{'rank': '64', 'song': 'Graveyard', 'singer': 'Halsey'}
{'rank': '65', 'song': 'What She Wants Tonight', 'singer': 'Luke Bryan'}
{'rank': '66', 'song': 'No Idea', 'singer': 'Don Toliver'}
{'rank': '67', 'song': "Ridin' Roads", 'singer': 'Dustin Lynch'}
{'rank': '68', 'song': 'More Hearts Than Mine', 'singer': 'Ingrid Andress'}
{'rank': '69', 'song': 'SUGAR', 'singer': 'BrockHampton'}
{'rank': '70', 'song': 'I Wish Grandpas Never Died', 'singer': 'Riley Green'}
{'rank': '71', 'song': 'Start Wit Me', 'singer': 'Roddy Ricch & Gunna'}
{'rank': '72', 'song': 'Make Me Want To', 'singer': 'Jimmie Allen'}
{'rank': '73', 'song': 'Say So', 'singer': 'Doja Cat'}
{'rank': '74', 'song': 'We Back', 'singer': 'Jason Aldean'}
{'rank': '75', 'song': "I Hope You're Happy Now", 'singer': 'Carly Pearce & Lee Brice'}
{'rank': '76', 'song': 'homecoming queen?', 'singer': 'Kelsea Ballerini'}
{'rank': '77', 'song': 'U Played', 'singer': 'MoneyBagg Yo Featuring Lil Baby'}
{'rank': '78', 'song': 'Blue World', 'singer': 'Mac Miller'}
{'rank': '79', 'song': 'Make No Sense', 'singer': 'YoungBoy Never Broke Again'}
{'rank': '80', 'song': 'Letter To Nipsey', 'singer': 'Meek Mill Featuring Roddy Ricch'}
{'rank': '81', 'song': 'Jerry Sprunger', 'singer': 'Tory Lanez & T-Pain'}
{'rank': '82', 'song': "Chasin' You", 'singer': 'Morgan Wallen'}
{'rank': '83', 'song': 'Rare', 'singer': 'Selena Gomez'}
{'rank': '84', 'song': 'Slow Dance In A Parking Lot', 'singer': 'Jordan Davis'}
{'rank': '85', 'song': 'Before You Go', 'singer': 'Lewis Capaldi'}
{'rank': '86', 'song': 'Those Kinda Nights', 'singer': 'Eminem Featuring Ed Sheeran'}
{'rank': '87', 'song': 'Vete', 'singer': 'Bad Bunny'}
{'rank': '88', 'song': 'Homemade', 'singer': 'Jake Owen'}
{'rank': '89', 'song': 'Easy', 'singer': 'DaniLeigh Featuring Chris Brown'}
{'rank': '90', 'song': 'Come Thru', 'singer': 'Summer Walker & Usher'}
{'rank': '91', 'song': 'Darkness', 'singer': 'Eminem'}
{'rank': '92', 'song': 'Camelot', 'singer': 'NLE Choppa'}
{'rank': '93', 'song': 'Underdog', 'singer': 'Alicia Keys'}
{'rank': '94', 'song': 'First Man', 'singer': 'Camila Cabello'}
{'rank': '95', 'song': 'What If I Told You That I Love You', 'singer': 'Ali Gatie'}
{'rank': '96', 'song': 'Catch', 'singer': 'Brett Young'}
{'rank': '97', 'song': 'Unaccommodating', 'singer': 'Eminem Featuring Young M.A'}
{'rank': '98', 'song': 'July', 'singer': 'Noah Cyrus Featuring Leon Bridges'}
{'rank': '99', 'song': "You Gon' Learn", 'singer': 'Eminem Featuring Royce da 5\'9" & White Gold'}
{'rank': '100', 'song': 'Dive Bar', 'singer': 'Garth Brooks & Blake Shelton'}
profile
wanna be good developer

0개의 댓글