크롤링 기초

가비·2022년 3월 26일
1

YBIGTA

목록 보기
1/6

크롤링을 위해서는 HTML언어에 관해 조금 알아둘 필요가 있다.
f12를 눌러 크롬 개발자모드에 들어가면 여러 태그들을 볼 수 있고 copy selector를 통해 복사할 수도 있고 ctrl+f로 원하는 태그가 잘 선택되었는지 확인할 수 있다.
CSS Selector에는 네가지 정도가 존재한다.

1. 태그 선택자

<h1>제목</h1> 👉 h1

2. ID 선택자

<div id = "aaa"> 안녕 </div> 👉#aaa

3. Class 선택자

<div class="aaa"> 안녕 </div> 👉.aaa

4. 자식 선택자

<div class="aaa"> <span> 안녕 </span> </div>
👉.aaa > span

2번째 자식태그 선택
<div class="aaa"> <span> 안녕 </span> <span> 바이 </span> </div>
👉.aaa > span : nth-child(2)


크롤링은 보통 BeautifulSoup와 Selenium을 이용하여 많이 진행한다.

📌BeautifulSoup

BTS기사에 대한 크롤링을 진행하였다.

from bs4 import BeautifulSoup
import requests
#Get 요청, naver 서버에 대화 시도
response = requests.get('https://search.naver.com/search.naver?where=news&sm=tab_pge&query=BTS&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=56&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start=1')

#네이버에서 html 제공, text 메소드로 태그 내 텍스트만 추출
html = response.text

#html 번역선생님으로 수프 만듦
soup = BeautifulSoup(html, 'html.parser')

titles = soup.select('a.news_tit')

for title in titles:
  art_title = title.text
  link = title.attrs['href']
  print(art_title, link)

1~10페이지의 기사를 크롤링하였다. 기사 url의 끝부분을 fstring으로 바꿔가면서 크롤링하였다.

pageNum=1
#1, 11, 21....91
for page in range(1,100,10):
  print(f'{pageNum}번째 페이지입니다.')
  #Get 요청, naver 서버에 대화 시도
  response = requests.get(f'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=BTS&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=56&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start={page}')

  #네이버에서 html 제공, text 메소드로 태그 내 텍스트만 추출
  html = response.text

  #html 번역선생님으로 수프 만듦
  soup = BeautifulSoup(html, 'html.parser')

  titles = soup.select('a.news_tit')

  for title in titles:
    art_title = title.text
    link = title.attrs['href']
    print(art_title, link)

  pageNum += 1

📌Selenium

저번에 셀레니움을 설치할 때 크롬드라이버로인해 얼마나 오류가 많이 났었는지 모른다 ㅜ 그런데 셀레니움이 업데이트 되면서 크롬드라이버매니저가 생겨서 자동으로 관리를 해준다는 꿀팁을 얻었다!!🥰

pip install selenium
pip install --upgrade selenium
pip install webdriver_manager
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager  # 크롬드라이버 자동업데이트
import time

service = Service(executable_path=ChromeDriverManager().install())
browser = webdriver.Chrome(service=service)

아마 파이썬으로 해당코드를 돌리면 잘 실행이 되는 것 같은데, 코랩에서 돌리니까 계속 에러가 났다. 그래서 구글링을 통해 다시 찾아봤다.

pip install selenium
pip install --upgrade selenium
pip install webdriver_manager
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager  # 크롬드라이버 자동업데이트
import time
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
browser = webdriver.Chrome('chromedriver',chrome_options=chrome_options)

이게 정확히 뭔진 잘 모르는데;;; 이러니까 잘 돌아가더라😊
네이버 > 쇼핑 > 검색창에 아이폰13 검색 > 맨 밑까지 커서 내리기 > 쇼핑리스트 크롤링

#웹페이지주소이동
browser.get("https://www.naver.com")
time.sleep(2)

browser.find_element(By.CSS_SELECTOR,'a.nav.shop').click()
time.sleep(1)

#검색창 찾기 = 클릭
search = browser.find_element(By.CSS_SELECTOR, 'input.co_srh_input._input ')

#검색어 입력
search.send_keys('아이폰13')
search.send_keys(Keys.ENTER)
time.sleep(2)



# 스크롤 전 높이
before_h = browser.execute_script("return window.scrollY") #execute_script = 자바스크립트 명령어 실행

# 무한 스크롤 - 반복문
while True:
    # 맨 아래로 스크롤을 내린다. body = 모든 웹사이트에 존재
    # 키보드의 END키 누르면 웹페이지 맨아래로이동
    browser.find_element(By.CSS_SELECTOR, "body").send_keys(Keys.END)
    time.sleep(1) # 스크롤 사이 페이지 로딩시간
    after_h = browser.execute_script("return window.scrollY")

    if after_h == before_h:
        break
    before_h = after_h  # 스크롤 후 높이가 다르면 before_h를 업데이트

items = browser.find_elements(By.CSS_SELECTOR, 'li.basicList_item__2XT81')
lst=[]
i=1
for item in items:
  name = item.find_element(By.CSS_SELECTOR, 'div.basicList_title__3P9Q7').text
  price = item.find_element(By.CSS_SELECTOR, 'span.price_num__2WUXn').text
  link = item.find_element(By.CSS_SELECTOR, 'div > a.basicList_link__1MaTN').get_attribute('href')
  print(i,name, price,link)
  i += 1

크롤링한 쇼핑리스트에서 핫딜상품을 제거해 주었다. (try-except구문을 사용하였는데, try에서 오류가 나면 except로 넘어간다.) 추가로 openpyxl을 사용하여 크롤링한 결과물을 엑셀파일로 저장해 보았다.

import openpyxl
from openpyxl import Workbook
wb = Workbook()
sheet = wb.active
sheet.append(['Ranking','Name','Price','Link'])
#웹페이지주소이동
browser.get("https://search.shopping.naver.com/search/all?query=%EC%95%84%EC%9D%B4%ED%8F%B013&cat_id=&frm=NVSHATC")
time.sleep(2)

# 스크롤 전 높이
before_h = browser.execute_script("return window.scrollY") #execute_script = 자바스크립트 명령어 실행

# 무한 스크롤 - 반복문
while True:
    # 맨 아래로 스크롤을 내린다. body = 모든 웹사이트에 존재
    # 키보드의 END키 누르면 웹페이지 맨아래로이동
    browser.find_element(By.CSS_SELECTOR, "body").send_keys(Keys.END)
    time.sleep(1) # 스크롤 사이 페이지 로딩시간
    after_h = browser.execute_script("return window.scrollY")

    if after_h == before_h:
        break
    before_h = after_h  # 스크롤 후 높이가 다르면 before_h를 업데이트

items = browser.find_elements(By.CSS_SELECTOR, 'li.basicList_item__2XT81')


i=1
for item in items:
  try:
     hotdeal = item.find_element(By.CSS_SELECTOR, 'span.thumbnail_sale__T-L2g').text
     continue
  except:
    name = item.find_element(By.CSS_SELECTOR, 'div.basicList_title__3P9Q7').text
    price = item.find_element(By.CSS_SELECTOR, 'span.price_num__2WUXn').text
    link = item.find_element(By.CSS_SELECTOR, 'div > a.basicList_link__1MaTN').get_attribute('href')
    sheet.append([i,name, price,link])
    i += 1
    
#간격조절
sheet.column_dimensions['A'].width = 10
sheet.column_dimensions['B'].width = 30
sheet.column_dimensions['C'].width = 20
sheet.column_dimensions['D'].width = 40

#크롤링 데이터 저장
wb.save(filename='iphone13_nohotdeal_crawling.xlsx')

추가로 네이버이미지검색에서 강아지를 쳤을 때 나오는 사진들을 크롤링해보았다. 나중에 이미지와 관련된 프로젝트를 하면 유용하게 사용할 수 있을 것 같다.

#from selenium import webdriver
#from selenium.webdriver.chrome.service import Service
#from webdriver_manager.chrome import ChromeDriverManager
#from selenium.webdriver.common.keys import Keys
#from selenium.webdriver.common.by import By
#import time
import os
import urllib.request  # 이미지 저장 모듈

#service = Service(executable_path=ChromeDriverManager().install())

# 사용자 정의 검색어 받아오기 - Type your answer
keyword = "강아지"

# 폴더 만들기
if not os.path.exists(f'{keyword}'):   # 해당 폴더의 존재여부를 boolean값으로 출력해줌
    # not True = False : 해당폴더가 기존에 존재하지 않으면 새 폴더를 만든다!
    os.mkdir(f'{keyword}')  

url = f'https://search.naver.com/search.naver?sm=tab_hty.top&where=image&query={keyword}'
#browser = webdriver.Chrome(service=service)
browser.implicitly_wait(5) 
browser.maximize_window() # 화면크기 최대화
browser.get(url)  
time.sleep(2)

# 무한스크롤 
# 스크롤 전 높이
before_h = browser.execute_script("return window.scrollY") #execute_script = 자바스크립트 명령어 실행

# 무한 스크롤 - 반복문
while True:
    # 맨 아래로 스크롤을 내린다. body = 모든 웹사이트에 존재
    # 키보드의 END키 누르면 웹페이지 맨아래로이동
    browser.find_element(By.CSS_SELECTOR, "body").send_keys(Keys.END)
    time.sleep(1) # 스크롤 사이 페이지 로딩시간
    after_h = browser.execute_script("return window.scrollY")

    if after_h == before_h:
        break
    before_h = after_h  # 스크롤 후 높이가 다르면 before_h를 업데이트


# 이미지 태그 추출
imgs = browser.find_elements(By.CSS_SELECTOR, 'img._image._listImage')

for i, img in enumerate(imgs, 1):   # enumerate(대상, 시작값)
    # 이미지 다운을 위해선 태그에있는 이미지의 주소가 필요하다.
		# Type your answer
    img_src = img.get_attribute('src')
    print(i, img_src)
    # img를 index값의 파일명으로 png파일로 저장
    urllib.request.urlretrieve(img_src, f'{keyword}/{i}.png')

Reference

열심히 교육해주신...
https://flannel-gardenia-fde.notion.site/5688867ae21f4ca0a66e4725a8f1ef34

profile
개발데분꿈나무🌳

0개의 댓글

관련 채용 정보