본문 바로가기
개발일지/selenium, BeautifulSoup, requests

Python 라이브러리를 통해 오피넷 데이터 스크래핑 후 엑셀저장

by 다니엘의 개발 이야기 2022. 7. 21.
320x100

그러고보면 이번 데이터를 수집하는거 자체만으로,

이전에는 넘사벽이였던 것같던데 가능해진게 믿기질 않는다.

 

미리 말하자면 데이터에 결측치는 있는것같다.

3번 반복문 돌려봤는데, 1,2개정도는 길이값에서 차이가 나더라.

 

그리고 이번 데이터 수집을 통해서도 스스로의 과제를 발견했다.

 

1. 결측치 없이 데이터 스크래핑이 가능한가?

2. 보다 반복문을 간결하게 만들기 위해서 내가 원하는 전체 데이터를 감싸고 있는 태그를 추출하고, 그것을 활용하는 방법을 익히자.

특히!! selenium 영역의 메인태그 설정 후 서브 태그로 이어지는 건 뭔가 작동이 안되더라; 기능은 있을거고 내가 방법을 모르는 것일테니 이부분을 중점적으로 공부해보자.

 

# Oil Data

from selenium import webdriver
from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By
from tqdm import tqdm
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

import chromedriver_autoinstaller
import pandas as pd
import time
import re
# chrome driver 생성
chromedriver_autoinstaller.install()
url = 'https://www.opinet.co.kr/searRgSelect.do'
driver = webdriver.Chrome('/Users/daniel_choi/miniforge3/envs/ds_study/lib/python3.10/site-packages/chromedriver_autoinstaller/103/chromedriver')
driver.get(url)
driver.get(url)
# 화면 최대화
driver.maximize_window()
# 지역 첫번째 영역에 서울 넣기
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'select#SIDO_NM0'))).send_keys('서울')
# 구 리스트 가져오기
df_starbucks = pd.read_excel('../Starbucks/starbucks_data.xlsx')
gu_list = df_starbucks.구.unique()


# 테스트 영역

## 테스트 영역

# 지역 두번째 영역에 각 구 넣어주기 테스트
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'select#SIGUNGU_NM0'))).send_keys(gu_list[0])
# 각 주유소 정보 리스트 화 후 테스트

# 이건 각 구 마다 변동사항이 있으니, 반드시 대기해주기
# main = driver.find_elements(By.CSS_SELECTOR, 'tbody#body1 > tr')[0].text
# main = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'tbody#body1 > tr > td.rlist')))
# len(main)

# 이건 selenium 버전이였다. main loop로 설정해 주었으나, 그 main loop에서 태그를 가져오는건 이렇게해도, 저렇게 해도 실패했다.
# 내가 하는 방법을 모르는 것같다. 이건 반드시 공부해보도록 하자.
# BeautifulSoup로 진행하자.
# BeautifulSoup를 통한 elements 접근

html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
# soup
# 잘 작동 되는 것같다.

# 잘 작동 되는 것 같다.
# len(soup.select('tbody#body1 > tr > td.rlist'))
# 34
main = soup.select('tbody#body1 > tr > td.rlist')
# 브랜드 네임
# main[0]('img')[0]['alt']

# 상호명
# 상호명 진행시 (현대오일뱅크(주)...)처럼 잘리는 게 있어서 이건 다시금 시도해봐야할 것같다.
# 다시 selenium!!
# 클릭 후 나온 페이지의 정보 추출 하기

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

sub = soup.select('div#os_dtail_info > div.inner')

# 상호명
# sub[0]('label')[0].text

# 연락처
# sub[0]('label')[1].text

# 주소
# sub[0]('label')[2].text

# 브랜드
# sub[0]('label')[3].text

# 고급 휘발유
# sub[0]('label')[4].text

# 보통 휘발유
# sub[0]('label')[6].text

# 경유
# sub[0]('label')[8].text


# 하나의 메인 안에 가둬두고 싶지만, 지금은 이게 메인이 아니니 이정도로 만족하고 다음번에 반드시 복습해보자.
# 부가정보 메인루프

# 굳 이정도면 준비 끝이다.
(soup.select('div.service > img')
# 테스트 구간

# 지역 첫번째 영역에 서울 넣기
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'select#SIDO_NM0'))).send_keys('서울')

# 구 리스트 가져오기
df_starbucks = pd.read_excel('../Starbucks/starbucks_data.xlsx')
gu_list = df_starbucks.구.unique()

# 최종 결과물 담을 그릇
oil_datas = []

for a in tqdm(gu_list):
    # 지역 두번째 영역에 각 구 넣어주기 테스트
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'select#SIGUNGU_NM0'))).send_keys(a)

    # 각 구별로 펼쳐지는 정보가 다를테니 main loop 용 재설정
    main = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'tbody#body1 > tr > td.rlist')))
    for b in main:
        b.click()
        
        html = driver.page_source
        soup = BeautifulSoup(html, 'html.parser')
        sub = soup.select('div#os_dtail_info > div.inner')

        for c in sub:
            # 상호명
            name = c('label')[0].text

            # 연락처
            call_number = c('label')[1].text

            # 주소
            address = c('label')[2].text

            # 브랜드
            brand = c('label')[3].text

            # 고급 휘발유
            fancy = c('label')[4].text

            # 보통 휘발유
            nomal = c('label')[6].text

            # 경유
            diesel = c('label')[8].text
            
            # service loop
            service = soup.select('div.service > img')
            
            # 세차장
            car_wash = 'on' if 'off' not in service[0]['src'] else 'off'
            # 충전소
            charge = 'on' if 'off' not in service[1]['src'] else 'off'
            # 경정비
            repair = 'on' if 'off' not in service[2]['src'] else 'off'           
            # 편의점
            convinien = 'on' if 'off' not in service[3]['src'] else 'off'
            # 24시영업
            oper24 = 'on' if 'off' not in service[4]['src'] else 'off'
            
            total = {
                '상호명': name,
                '연락처': call_number,
                '주소': address,
                '브랜드': brand,
                '고급휘발유': fancy,
                '보통휘발유': nomal,
                '경유': diesel,
                '세차장' : car_wash,
                '충전소':charge,
                '경정비':repair,
                '편의점':convinien,
                '24시영업':oper24
            }
            oil_datas.append(total)
len(oil_datas)
# 443
oil_datas[150]

'''
{'상호명': '현대오일뱅크㈜직영 흑석동셀프주유소',
 '연락처': '02-815-0724',
 '주소': '서울 동작구 현충로 101 (흑석동)',
 '브랜드': '현대오일뱅크',
 '고급휘발유': '2,187',
 '보통휘발유': '1,949',
 '경유': '2,091',
 '세차장': 'on',
 '충전소': 'off',
 '경정비': 'off',
 '편의점': 'off',
 '24시영업': 'on'}
 '''
df_oil = pd.DataFrame(oil_datas)
df_oil.tail()
df_oil.to_excel('oil.xlsx')

 

생각외로 간촐한 느낌이지만,

이것을 더욱 간소화 시키기 위해서 더욱! 기초 공부에 매진하자.

기초를 더 공부하지 않았으면 이거 아직도 헤매고 건드리지도 못했을 것이다.

300x250