[4.19 TIL]셀레니움, BeautifulSoup 크롤링

셀레니움과 BeautifulSoup를 활용해서 멜론, 지니, 바이브, 플로에 내가 찾고자 하는 음악이 있는지 확인해 보고자 한다.

  1. 구상
    selenium - 동적 웹페이지 접근
    BeautifulSoup - 웹페이지 소스 크롤링, 원하는 값 찾기
  1. 코드
from selenium import webdriver
from bs4 import BeautifulSoup
import time

url_list = {"vibe": "https://vibe.naver.com/search?query=",
            "melon": "https://www.melon.com/search/total/index.htm?q=",
            "geine": "https://www.genie.co.kr/search/searchMain?query=",
            "flo": "https://www.music-flo.com/search/all?keyword="}

class Migrator:
    def __init__(self):
        chrome_options = webdriver.ChromeOptions()
        chrome_options.headless = True
        chrome_options.add_argument('--no-sandbox')
        chrome_options.add_argument('--disable-dev-shm-usage')
        chrome_options.add_argument('window-size=1920x1080')
        self.driver = webdriver.Chrome(options=chrome_options)
        self.driver.implicitly_wait(10)

    def crawl_list(self, seq):
        try:
            for url in url_list:
                self.driver.get(url_list[url] + seq)
                time.sleep(1)
                if url == "vibe":
                    self.driver.find_element_by_css_selector('#app > div.modal > div > div > a.btn_close').click()
                    time.sleep(1)
                    html = self.driver.page_source
                    soup_vibe = BeautifulSoup(html, 'html.parser')
                    musics_vibe = soup_vibe.select('#content > div:nth-child(3) > div > div:nth-child(1) > div:nth-child(1) > div.info_area > div.title > span.inner > a > span')[0].text
                    print(url,": ", musics_vibe)

                elif url == "melon":
                    html = self.driver.page_source
                    soup_melon = BeautifulSoup(html, 'html.parser')
                    musics_melon = soup_melon.select('#frm_searchSong > div > table > tbody > tr:nth-child(1) > td:nth-child(3) > div > div > a.fc_gray > b')[0].text
                    print(url,": ",musics_melon)

                elif url == "geine":
                    html = self.driver.page_source
                    soup_geine = BeautifulSoup(html, 'html.parser')
                    musics_geine = soup_geine.select('#body-content > div.search_song > div.search_result_detail > div > table > tbody > tr:nth-child(1) > td.info > a.title.ellipsis > span.t_point')[0].text
                    print(url,": ",musics_geine)

                elif url == "flo":
                    html = self.driver.page_source
                    soup_flo = BeautifulSoup(html, 'html.parser')
                    musics_flo = soup_flo.select('#main > div > div:nth-child(3) > div.search_section_top_badge > div > div.badge_track_info > div.info_area > p.title > a')[0].text
                    print(url,": ",musics_flo)
        except:
            self.shutdown()

    def shutdown(self):
        self.driver.close()


migrator = Migrator()
migrator.crawl_list('금요일에 만나요')
migrator.shutdown()
  1. 해석
    -각 플랫폼에 해당하는 url을 쿼리 값만 비워둔 채 딕셔너리에 저장.
    -Migrator 클래스 생성자에서 크롬 드라이버 기본 설정값 저장
    -crawl_list 메서드에서 각 플랫폼별로 크롤링을 진행.
  1. 문제점
    -값이 크롤링이 될 때가 있고 안될때가 있다.

  2. 해결방안
    -time.sleep()을 활용해서 크롤링할 웹페이지가 충분하게 값을 받아오게 한 후 크롤링 한다.
    -self.driver.implicitly_wait(10)도 동일.
    -완벽하게 해결되지 않았지만 80프로의 확률로 크롤링이 잘 된다.
    -해당 코드를 멀티 프로세싱하면 확률이 높아진다고 한다. 다음에 해봐야지.
    -클라우드에 올려서 ip값을 바꿔준다면 확률이 높아진다고 한다. 이것도 다음에.

※실행 결과 화면

좋은 웹페이지 즐겨찾기