조종 다음은 개발

그동안 코드잇을 통해서 "데이터 사이언스 입문" 강의를 듣고 "업무자동화 FOR WINDOWS" 도 들으면서 많은 지식을 얻었다. 이제 필요한 것은 바로 적용!! 그래서 기존에 하고 있었던 중고나라 크롤링의 코드에 여러 기능을 추가했다

 

 

from selenium import webdriver
import time
from openpyxl import Workbook
import datetime
from selenium.webdriver.common.keys import Keys
import pyperclip
import pandas as pd


# 검색할 물건
thing = '맥북 m1'

# 총 몇 페이지 자료를 모을지 선택
total_page = 354

# 페이지 개수 나누기
total_next = total_page // 10
last_page = total_page - total_next * 10

# datetime
now = datetime.datetime.now()
today = now.strftime('%Y-%m-%d')

# 엑셀
wb = Workbook(write_only=True)
ws = wb.create_sheet(today)
ws.append(['작성날짜', '판매 상태', '제목', 'url', '가격'])

# 중고나라 들어가기
driver = webdriver.Chrome()
driver.implicitly_wait(3)
driver.get('https://cafe.naver.com/joonggonara')
driver.maximize_window()
time.sleep(1)

# 로그인 버튼을 찾고 클릭합니다.
login_btn = driver.find_element_by_css_selector('#gnb_login_button')
login_btn.click()
time.sleep(1)

# id, pw 입력할 곳을 찾습니다.
tag_id = driver.find_element_by_name('id')
tag_pw = driver.find_element_by_name('pw')
tag_id.clear()
time.sleep(1)

# id 입력
tag_id.click()
pyperclip.copy('####')
tag_id.send_keys(Keys.CONTROL, 'v')
time.sleep(1)

# pw 입력
tag_pw.click()
pyperclip.copy('####')
tag_pw.send_keys(Keys.CONTROL, 'v')
time.sleep(1)

# 로그인 버튼을 클릭합니다
login_btn = driver.find_element_by_id('log.login')
login_btn.click()

# 검색
driver.find_element_by_css_selector('#topLayerQueryInput').send_keys(thing)
driver.find_element_by_css_selector('#cafe-search .btn').click()
time.sleep(1)

# iframe 들어가기
driver.switch_to.frame('cafe_main')

# 제목만으로 바꾸기
driver.find_element_by_css_selector('#currentSearchByTop').click()
time.sleep(1)
driver.find_elements_by_css_selector('#sl_general li')[1].click()
time.sleep(1)
driver.find_element_by_css_selector('.btn-search-green').click()
time.sleep(1)

# 크롤링 함수 정의(만약 "이전" 버튼이 있으면 num은 1 아니면 0)
def crolling(num):
    # 게시글 들어가는 반복문
    with_before = 0
    for i in range(len(driver.find_elements_by_css_selector('.article'))):

        # 게시글 들어가기
        articles = driver.find_elements_by_css_selector('a.article')[i]
        articles.click()
        time.sleep(1)

        # 정보추출
        write_date = driver.find_element_by_css_selector('.date').text
        product_title = driver.find_element_by_css_selector('h3.title_text').text
        url = driver.find_element_by_css_selector('.button_url').get_attribute('href')
        # 가격을 못찾으면 그냥 빈칸 입력
        try:
            # 가격 문자열을 숫자로 바꾸기
            product_price_str = driver.find_element_by_css_selector('.ProductPrice').text
            price_no_won = product_price_str[:-1]
            price_no_won_shim = price_no_won.replace(',', '')
            product_price = int(price_no_won_shim)
        except:
            # 제목에서 가격 문자열 추출
            try:
                product_title = product_title.replace('[', '')
                product_title = product_title.replace(']', '&')
                product_price_str = product_title.split('&')[-2]

                # 가격 문자열을 숫자로 바꾸기
                price_no_won = product_price_str[:-1]
                price_no_won_shim = price_no_won.replace(',', '')
                product_price = int(price_no_won_shim)
            except:
                product_price = ''
        # 판매 상태 정보 저장
        try:
            status = driver.find_element_by_css_selector('.SaleLabel').text
        except:
            status = ""

        # 엑셀에 작성
        ws.append([write_date, status, product_title, url, product_price])

        # 뒤로가기
        driver.back()
        driver.switch_to.frame('cafe_main')

    # 다음 게시글 page 이동
    pages = driver.find_elements_by_css_selector('.prev-next a')[page + 1 + num]
    pages.click()

for i in range(total_next):
    # 마지막 10단위 페이지일 때
    if i == 0:
        # 다음페이지 클릭 반복문
        for page in range(10):
            crolling(0)
    elif i > 0 and i != total_next-1:
        for page in range(10):
            crolling(1)
    elif i == total_next-1:
        for page in range(last_page):
            crolling(1)


# selenium 끝내고 엑셀 파일 저장
driver.quit()
wb.save(f'중고나라 {today}{thing} 매물.xlsx')

# 데이터프레임 생성
df = pd.read_excel(f'C:\\Users\\82102\\PycharmProjects\\CoditFrist\\news\\mail\\중고나라 {today}{thing} 매물.xlsx')

# 가격이 비이상적인 데이터 삭제하기
q1 = df['가격'].quantile(0.25)
q3 = df['가격'].quantile(0.75)
iqr = q3 - q1
condition = (df['가격'] > q3 + 1.5 * iqr) | (df['가격'] < q1 - 1.5 * iqr)
df.drop(df[condition].index, inplace=True)

print(df.describe())

 

 

 

너무 갑자기 이것 저것 추가 되었나? ㅎㅎ

 

 

 

 

 

 

 

사실 이 코드들은 하루 아침에 만든게 아니라 

 

며칠동안 계속 만지면서 이것 저것 추가된 것이다

 

(블로그에 포스팅하기 귀찮아서 못 올렸다,,)

 

 

 

 

 

일단 코드가 진행되는 순서에 따라서 설명하자면

 

 

 

 

 

먼저 검색할 물건을 정의한다. 

 

나는 요즘 맥북에 관심이 많아서 맥북으로 정했다.

 

 

 

그리고 몇 페이지 까지 정보를 가져올지 정한다.

 

많으면 많을수록 더 정확한 정보를 얻을 수 있다.

 

나는 354페이지로 정했다.

 

 

 

그리고 정한 페이지를 10단위로 나눈다.

 

왜냐하면 한번에 1페이지부터 10페이지까지

 

나오고 그 뒤로는 다음페이지를 클릭해야

 

11페이지부터 20페이지 까지 나오기 때문이다.

 

 

 

그리고 중고나라에 들어간다음

 

네이버 로그인을 한다.

 

그런데 여기서 첫번째 문제가 발생했었다.

 

 

 

문제1)

 

바로 로그인을 할 때 아이디와 비밀번호 부분에

 

직접 selenium으로 선택하면 네이버에서

 

로봇으로 인지하고 로그인시 화면에 보이는 

 

번호를 입력하라고 나온다..

 

 

 

당연히 프로그램을 진행 할 때 마다 

 

화면에 출력되는 번호는 다르기 때문에

 

프로그램을 실행할 수 없었다.. 그래서

 

해결방법을 찾기 위해서 열심히 구글링을 했다.

 

 

 

그러다가 찾은 방법이 바로 아이디와 비번을 복사한 다음에

 

붙여넣기를 하는방법이다. 이 방법을 이용하면

 

더이상 로봇인지 판단하는 인증절차가 생기지 않는다.

 

 

 

 

계속 진행해서 카페에서 맥북을 검색한 다음에

 

"제목만" 을 선택하여 검색하도록 했다.

 

왜냐하면 "제목 + 내용" 을 선택하면

 

판매 내용이 아닌 것들이 너무 많이 나왔다.

 

 

 

그리고 네이버 카페는 iframe이라는 테그 안에서 

 

정보를 구할 수 있어서 iframe으로 일단 들어가야 한다.

 

그 다음에 정보를 가져올 수 있다.

 

 

 

그리고 크롤링 시작.

 

 

크롤링하여 얻어진 정보를 확인해보니까 문제점을 발견했다.

 

 

문제 2)

가격 정보가 없는 것들이 있었다.

 

가격 정보를 얻어 올 때 중고나라 게시글 규격에 맞춰져

 

가격 정보가 있는 곳에서 정보를 가져왔는데

 

만약 게시글 작성자가 이 규격을 따르지 않거나

 

공식앱을 이용하여 게시글을 등록한 경우에는

 

가격 정보를 가져올 수 없었다.....

 

 

 

 그러나 이런 경우에는 대부분 제목 부분에 대괄호로 가격 정보다 들어있었다.

 

ex)[공식앱][맥북 팔아요~][1,000,000원]

 

어느정도 규칙이 있는 제목이였다.

 

그래서 이 제목에서 가격 정보가 들어있는 대괄호에서 정보를 꺼내서 

 

가격 칼럼에 등록하는 방법을 선택했다.

 

일단 대괄호를 지운다음에 '&' 로 split 하고

 

split된 정보에서 가격 정보다 있는 부분을 인덱싱 하여 정보를 추출했다.

 

 

 

 

그리고 가격 정보가 문자열로 저장되어서 

 

정수로 바꿔주었다. 그래야 엑셀에서  가격순으로

 

정렬할 때 낮은 가격부터 정렬되는 데이터를 볼 수 있기 때문이다.

 

profile

조종 다음은 개발

@타칸

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!