Python 크롤링, 파이썬끝~

정원·2022년 7월 7일

Python

목록 보기
7/7

22.07.07 파이썬 끝

  • 엑셀파일 형식으로 크롤링 진행해보기
  • 이미지를 바이트로 변환해서 파일에 저장

엑셀 처리 모듈 임포트

  • 라이브러리 다운 - cmd - pip install XlsxWriter

user-agent 정보를 변환해 주는 모듈

  • 라이브러리 다운 - cmd - pip install fake_useragent

crawler_aladin03

<script>

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import time
from datetime import datetime
from bs4 import BeautifulSoup

# 이미지를 바이트 변환 처리 모듈
from io import BytesIO

# 엑셀 처리 모듈 임포트
import xlsxwriter

# user-agent 정보를 변환해 주는 모듈 임포트
# 특정 브라우저로 크롤링을 진행할 때 차단되는 것을 방지
from fake_useragent import UserAgent

# 요청 헤더 정보를 꺼내올 수 있는 모듈
import urllib.request as req




d = datetime.today()

file_path = f'C:/Users/user/Desktop/java_web_LKM/python/crawling/알라딘 베스트셀러 1~400위(엑셀)_{d.year}_{d.month}_{d.day}.xlsx'

# User Agent 정보 변환 (필수는 아니에요.)
opener = req.build_opener() # 요청 헤더 정보를 초기화.
# ie, opera, chrome, firefox, safari, random
opener.addheaders = [('User-agent', UserAgent().random)]
req.install_opener(opener) # 새로운 헤더 정보를 삽입.

# 엑셀 처리 선언
# Workbook 객체를 생성하여 엑셀 파일을 하나 생성(매개값으로 저장될 경로를 지정.)
workbook = xlsxwriter.Workbook(file_path)

# 워크 시트 생성
worksheet = workbook.add_worksheet()

# 브라우저 안뜨게 하기
chrome_option = Options()
chrome_option.add_argument('--headless')

# 브라우저 설정 - 일반 모드
# driver = webdriver.Chrome('C:/Users/user/Desktop/java_web_LKM/python/chromedriver.exe')

# 브라우저 설정 - headless 모드
driver = webdriver.Chrome('C:/Users/user/Desktop/java_web_LKM/python/chromedriver.exe', options=chrome_option)

# 브라우저 사이즈 조정
driver.set_window_size(800, 600)

# 브라우저 내부 대기
# time.sleep(10) -> 브라우저 로딩에 상관없이 무조건 10초 대기

# 웹 페이지 전체가 로딩될 때 까지 대기 후 남은 시간 무시.
driver.implicitly_wait(10)

# 페이지 이동 (베스트 셀러 페이지)
driver.get('https://www.aladin.co.kr/shop/common/wbest.aspx?BranchType=1')

# 엑셀에 텍스트를 저장하기 위해 미리 컬럼 셋팅
cell_format = workbook.add_format({'bold':True, 'font_color':'red', 'bg_color':'yellow'})
worksheet.write('A1', '썸네일', cell_format)
worksheet.write('B1', '제목', cell_format)
worksheet.write('C1', '작가', cell_format)
worksheet.write('D1', '출판사', cell_format)
worksheet.write('E1', '출판일', cell_format)
worksheet.write('F1', '가격', cell_format)
worksheet.write('G1', '링크', cell_format)

cur_page_num = 2 # 현재 페이지 번호 (XPATH 활용)
target_page_num = 2 # 목적지 페이지 번호 (XPATH 활용)
rank = 1 # 순위
cnt = 2 # 엑셀 행 수 카운트 해줄 변수

worksheet.set_column('A:G', 25)


while True:
    # bs4 초기화
    soup = BeautifulSoup(driver.page_source, 'html.parser')

    div_ss_book_box_list = soup.find_all('div', class_='ss_book_box')

    for div_ss_book_box in div_ss_book_box_list:

        # 이미지
        img_url = div_ss_book_box.select_one('table div > a img.i_cover')
        if img_url == None:
            img_url = div_ss_book_box.select_one('table div > a img.front_cover')
        print(img_url)

        # 타이틀, 작가, 가격 정보를 모두 포함하는 ul부터 지목
        ul = div_ss_book_box.select_one('div.ss_book_list > ul')

        # 타이틀
        title = ul.select_one('li > a.bo3')

        # 작가
        author = title.find_parent().find_next_sibling()

        # 작가쪽 영역 데이터 상세 분해
        author_data = author.text.split(' | ')
        author_name = author_data[0].strip()
        company = author_data[1].strip()
        pub_day = author_data[2].strip()

        # 가격
        price = author.find_next_sibling()
        price_data = price.text.split(', ')[0]

        # 책 상세 정보 페이지 링크
        # title이란 변수에 a태그를 이미 지목해 놓은 상태.
        # title -> a태그의 요소 전부를 가지고 있는 상태
        # href로 작성된 키를 전달하고 해당 value를 받아 변수에 저장.
        page_link = title['href']

        try:
            # 이미지 바이트 변환 처리
            # BytesIO 객체의 매개값으로 아까 준비해 놓은 img 태그의 src값을 전달.
            img_data = BytesIO(req.urlopen(img_url['src']).read())

            # 엑셀에 이미지 저장
            # worksheet.insert_image('배치할 셀 번호', 이미지제목, {'image_data':바이트로 변환한 이미지, 기타 속성...})
            worksheet.insert_image(f'A{cnt}', img_url['src'], {'image_data':img_data, 'x_scale':0.5, 'y_scale':0.5})
        except:
            # 파이썬에서는 블록구조에 아무것도 쓰지 않으면 에러라서
            # 딱히 작성할 코드가 없을 때 pass를 사용.
            pass

        # 엑셀에 나머지 텍스트 저장
        worksheet.write(f'B{cnt}', title.text)
        worksheet.write(f'C{cnt}', author_name)
        worksheet.write(f'D{cnt}', company)
        worksheet.write(f'E{cnt}', pub_day)
        worksheet.write(f'F{cnt}', price_data)
        worksheet.write(f'G{cnt}', page_link)

        worksheet.set_row(cnt-1, 75)

        cnt += 1
        rank += 1
    
    # 한 페이지 크롤링 종료 후
    # 다음 페이지()로 전환
    cur_page_num += 1
    driver.find_element(By.XPATH, f'//*[@id="newbg_body"]/div[3]/ul/li[{cur_page_num}]/a').click()
    del(soup)
    time.sleep(3)

    if cur_page_num > target_page_num:
        print('크롤링 종료!')
        break # while True break

driver.close()
workbook.close()
</script>

melon_chart

<script>
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import time
from datetime import datetime
from bs4 import BeautifulSoup
from io import BytesIO
import xlsxwriter
from fake_useragent import UserAgent
import urllib.request as req

d = datetime.today()

file_path = f'C:/Users/user/Desktop/java_web_LKM/python/crawling/멜론일간차트순위 1~100위_{d.year}_{d.month}_{d.day}.xlsx'

opener = req.build_opener()
opener.addheaders = [('User-agent', UserAgent().random)]
req.install_opener(opener)

workbook = xlsxwriter.Workbook(file_path)

worksheet = workbook.add_worksheet()

browser = webdriver.Chrome('C:/Users/user/Desktop/java_web_LKM/python/chromedriver.exe')

browser.set_window_size(1280, 1024)

browser.get('https://www.melon.com/chart/day/index.htm')

browser.implicitly_wait(5)

worksheet.set_default_row(50)
worksheet.set_column('A:E', 25)

cell_format = workbook.add_format({'bold':True, 'font_color':'red', 'bg_color':'yellow', 'border':1})
worksheet.write('A1', '순위', cell_format)
worksheet.write('B1', '커버사진', cell_format)
worksheet.write('C1', '가수이름', cell_format)
worksheet.write('D1', '앨범명', cell_format)
worksheet.write('E1', '노래명', cell_format)

row_cnt = 2

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

for cnt in [50, 100]:
    song_tr_list = soup.select(f'#lst{cnt}')

    for song_tr in song_tr_list:

        # 순위 찾기
        rank = song_tr.select_one('div.wrap.t_center').text.strip()
        # print('순위' + rank)

        # 이미지 찾기
        img_tag = song_tr.select_one('div.wrap > a > img')
        img_url = img_tag['src']
        # print('이미지:', img_url)

        # 가수 이름
        artist_name = song_tr.select_one('div.wrap div.ellipsis.rank02 > a').text.strip()
        # print('가수이름:', artist_name)

        # 앨범명 찾기
        album_name = song_tr.select_one('div.wrap div.ellipsis.rank03 > a').text.strip()
        # print(album_name)

        # 노래명 찾기
        song_name = song_tr.select_one('div.wrap div.ellipsis.rank01 > span > a').text.strip()
        # print(song_name)

        # print('=' * 40)

        try:
            img_data = BytesIO(req.urlopen(img_url).read())
            worksheet.insert_image(f'B{row_cnt}', img_url, {'image_data':img_data})
        except:
            pass

        worksheet.write(f'A{row_cnt}', rank)
        worksheet.write(f'C{row_cnt}', artist_name)
        worksheet.write(f'D{row_cnt}', album_name)
        worksheet.write(f'E{row_cnt}', song_name)

        row_cnt += 1


workbook.close()
browser.close() 
</script>

img_colletor

  • 이미지 다운로드 후 경로에 폴더생성.
print('# 최초 실행 시 약간의 로딩이 발생할 수도 있으니 잠시만 기다려 주세요! (최대 1분)')
print('인터넷 연결이 되어 있어야 합니다.')

# 운영체제에서 제공되는 여러 기능 (폴더 생성)
import os
from selenium import webdriver
from bs4 import BeautifulSoup
import urllib.parse as rep
import urllib.request as req
import time
from fake_useragent import UserAgent

opener = req.build_opener()
opener.addheaders = [('User-agent', UserAgent().random)]
req.install_opener(opener)

# 다음 이미지 기본URL
base = 'https://search.daum.net/search?w=img&nil_search=btn&DA=NTB&enc=utf8&q='

print('### 검색어를 입력하시면 해당 검색어에 맞는 이미지를 다운로드 받습니다.')
print('### 이미지 자료는 daum 검색 자료를 활용하고, 개수는 첫페이지 기준으로 80개의 이미지를 가져옵니다.')
print('### 다운받은 이미지는 C드라이브 imagedown 폴더에 자동 저장됩니다.')

# 검색어 
s = input('### 검색어 입력: ')

'''
모든 브라우저에서 모든 서버에게 정확한 요청 데이터를 전달하기 위해
URL Encoding이 필요합니다.
URL에는 아스키 코드를 이용한 문자를 전달하는 것이 정석입니다.
타 언어로 작성된 문자를 변환해서 전달하는 것이 맞습니다.
'''
quote = rep.quote_plus(s)

# url = base + s
url = base + quote
print(url)

# 이미지 저장 경로 폴더 만들기
save_path = 'C:/imagedown/'

# 폴더 생성(예외 처리)
try:
    # 기존 폴더 있는 지 체크
    if not os.path.isdir(save_path):
        # 없다면 폴더 생성
        os.mkdir(save_path)
except OSError as e:
    print('폴더 생성 실패')
    print('폴더 이름:', e.filename)

browser = webdriver.Chrome('C:/Users/jwons/OneDrive/바탕 화면/java_web_JJW/python/chromedriver_win32/chromedriver.exe')
browser.get(url)

browser.implicitly_wait(5)

src = browser.page_source

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

img_list = soup.select('div.wrap_thumb > a.link_thumb > img')

# enumerate(컬렉션 자료, start index)
# 리스트, 튜플 등 컬렉션 자료형에서 요소와 순서값(index)를 동시에 전달받고 싶을 때 사용하는 내장 함수. 
for i, img in enumerate(img_list, 1):
    # 저장 파일명 및 경로
    full_file_name = os.path.join(save_path, save_path + str(i) + '.png')

    # 파일명
    print(full_file_name)

    # 다운로드 요청
    req.urlretrieve(img['data-src'], full_file_name)

# 다운 완료
print('download success')

# 다운로드 완료 후 다운로드 폴더 자동으로 열어주는 행위
path = os.path.realpath(save_path)
os.startfile(path)

print('5초 뒤 자동 종료됩니다.')
browser.close()
time.sleep(5)
  • 위에 작성한 파일을 파이썬없이 exe파일로 변환해서 사용할수 있게 변환
  • 라이브러리 다운 - cmd - pip install pyinstaller
  • 파일 경로로 이동(C:\Users\jwons\OneDrive\바탕 화면\java_web_JJW\python>)
  • pyinstaller --onefile img_collector.py(파일명)
    exe로 실행된다.

다른사람한테 배포할때는 exe파일 변환할때 만들어진 파일들을(build,dist,img_collector.spec) 압축해서 보내야한다.

0개의 댓글