ASAC 빅데이터 분석가 7기/ASAC 일일 기록

ASAC 빅데이터 분석가 과정 14일차 - 2 (24.12.23)

junslee 2024. 12. 23. 14:10

09_daum_site

  • 웹에 있는 데이터를 수집을 하고 싶을 때
    1) api : best
    2) 일반적인 사이트
        2-1) DART : 숨겨진 주소 잘 찾기 / 속도, ip로 방해받을 수 있음 (방어 전략)
        2-2) daum --> 금융 : 숨겨진 주소를 찾을 필요 X
            웹브라우저에서는 동작하지만 코드상에서 안될 때
            - user-agent : 접속하는 sw의 정보
            - referer : 해당 주소를 누가 호출
            etc cookies

  • 웹드라이버 : 직접 브라우저 컨트롤 하는 방법
    - 패키지 --> 셀레니움
    - 속도가 느리다
    - 로그인을 하기 싫다
    (셀레니움으로 로그인 => 빠르게 접속)

  • 결론 : 정해진 것은 없다 => 해야 하는 사이트에 맞춰서 해야 한다

import urllib.request
url = "https://finance.daum.net"
res = urllib.request.urlopen(url)
res.read().decode("utf-8")
# 종종 403 에러가 나타날 수 있음!!
# => 정보가 들어오기는 하는데 원하는 정보가 아니라는 뜻
# 출력 생략

url = "https://finance.daum.net/api/search/ranks?limit=10"
res = urllib.request.urlopen(url)
res.read().decode("utf-8")

  • 403에러가 나타나거나, 접근 권한이 없다고 할 때
    => 나는 브러우저입니다
    + referer : 포털에서 직접 호출
url = "https://finance.daum.net/api/search/ranks?limit=10"
req = urllib.request.Request(
    url,
    data = None,
    headers = {
        "referer": "https://finance.daum.net/",
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
    }
)
# 브라우저가 실제 요청했던 실질적인 요청 양식&정보들을 채워서 보내기
res = urllib.request.urlopen( req).read().decode("utf-8")
res
# 출력 생략 
  • requests 패키지에서
    => 변환이나 이런 샘플 url 제공을 requests
import requests
url = "https://finance.daum.net/api/search/ranks?limit=10"
headers = {
        "referer": "https://finance.daum.net/",
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
    }
# 요청 파라미터 : params --> 개발자도구(페이로드)
res = requests.get( url, headers=headers)
temp = res.text
temp
# 출력 생략
temp = res.json()
temp
# 출력 생략 
  • rank하고, 종목 이름, 현재 가격을 출력해보세요!!!!
for i in temp["data"]:
    print(i["rank"], i["name"], i["tradePrice"])
    print("*"*50)
1 삼성전자 53800
**************************************************
2 한미반도체 87800
**************************************************
3 셀트리온 193700
**************************************************
4 한화오션 35850
**************************************************
5 고려아연 1078000
**************************************************
6 SK하이닉스 171100
**************************************************
7 더본코리아 34500
**************************************************
8 기아 101000
**************************************************
9 카카오 39700
**************************************************
10 NAVER 201000
**************************************************
  • 403 에러 처리 하는 부분 :업종 상위

url = "https://finance.daum.net/api/sector/wics?perPage=5&order=desc"
headers = {
        "referer": "https://finance.daum.net/",
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
    }
# 요청 파라미터 : params -> 개발자도구(페이로드)
res = requests.get( url, headers=headers)
temp = res.text
temp
# 출력 생략

  • 정리)
    직접 찾아서 해보고, 처리하는 것 이외에는 답이 없다
    그냥 해보자
    난도가 높은 친구들이 있으니 고민을 해야 한다

10_selenium_localPC

  • pip install ~~ : 일반적인 파이썬 패키지 설치  (주피터 노트북에서는 !필요)
  • conda install ~~ : 아나콘다 이반으로 파이썬 패키지 설치
    => conda에서 있으면, 이것으로
    => 안되면 pip install ~~로 설치하기
  • 아나콘다 프롬포트는 관리자 권한 실행 => 팅김 방지

 

  1.  slelnium 패키지 설치
    => google : selenium anaconda, selenium install
    => 설치 : conda install ~~, pip install ~~
  2. 크롬 브라우저 설치

  3. 크롬 브라우저 컨트롤 할 webdriver

ref : https://sites.google.com/chromium.org/driver/getting-started

 

Chrome for Testing availability

chrome-headless-shellmac-arm64https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.204/mac-arm64/chrome-headless-shell-mac-arm64.zip200

googlechromelabs.github.io

ref : https://googlechromelabs.github.io/chrome-for-testing/

 

ChromeDriver - WebDriver for Chrome - Getting started

This page documents how to start using ChromeDriver for testing your website on desktop (Windows/Mac/Linux). You can also read Getting Started with Android or Getting Started with ChromeOS Setup ChromeDriver is a separate executable that Selenium WebDriver

sites.google.com


  • 본인 브라우저의 버전이랑 chroemdirver의 버전을 체크하자

  • 해당하는 본인 환경에 맞는 driver 다운 받기
  • 압축 명확하게 풀어야 한다
  • 편한 위치에 chromedrvier.exe 파일을 두고, 경로를 체크하자

  • 다운 받은 choromedrvier.exe 의 경로를 지정을 해야 한다
path = r"C:\Users\kwonm\Downloads\chromedriver-win64\chromedriver.exe"
  • 개인별로 본인 환경에 맞는 경로 지정을 해야 한다
  • 다운 받을 때 버전 체크
    압축을 풀고, 해제한 경로를 full 작성하는 것+ 파일명+ 확장자
  • 정규식 문자열로 한 이유 : \\ 윈도우에서 개발 경로 붙이기 귀찮아서

  • 접속에 필요한 모듈
from selenium import webdriver
from seleniuhttp://m.webdriver.chrome.service import Service
# chrome을 한 이유 : 크롬 브라우저를 통해서, 크롬 wedriver로 조절

  • 필요한 정보들을 접근을 하는게 목적 : By. 찾을 요소!!!!! ==> 셀레니움 4.X
  • By.~~~ : 필요한 정보들이 있는 요소를 중심으로 접근!!!!
from seleniuhttp://m.webdriver.common.by import By

  • opt) 키보드로 뭔가 조작을 해야한다거나 마우스로 뭔가할 때
from seleniuhttp://m.webdriver.common.keys import Keys

  • 참고: 셀레니움4에서는 기존과 다른게 접속을 한다
s = Service( path )
# 컨트롤 하려고하는 브라우저에 대한 변수화: driver
driver = webdriver.Chrome( service= s)

# 내가 웹브라우저에서 하는 모든 행동들을 코드로 제어할 수 있다
# 자세한 것은 메뉴얼 참조
driver.set_window_size(1000,1000)

# 내가 가려는 주소에
url = "https://naver.com"
driver.get(url)
# print(driver.page_source)

# 네이버 검색 창에 원하는 검색어를 입력하고 싶다
# 검색창의 검색어는
query_txt = "bts"
# 네이버 창의 어디에 이 검색어를 입력할지 지정
#     위치/요소 : xpath
#     규칙이 안 잡히면 : full_xpath, css, js, // tag + 속성들
element = driver.find_element( By.XPATH, '//*[@id="query"]')
element.send_keys( query_txt )
# 검색어 창에 btx라고 입력이 될 것이다

# 그 검색어로 조회를 하고자 하는  버튼 클릭
driver.find_element(By.XPATH, '//*[@id="search-btn"]').click()
# 참고) 화면 캡처
driver.save_screenshot("test_bts.png")
# 자동으로 브라우저 창 종료
driver.quit()

11_selenium_dart_re

from selenium import webdriver
from seleniuhttp://m.webdriver.chrome.service import Service
from seleniuhttp://m.webdriver.common.by import By
from seleniuhttp://m.webdriver.common.keys import Keys
import re
import time # 무조건 사용할 예정 : 셀레니움에서는 정보가 헛 돌 수 있다
import datetime # 파이썬에서 날짜, 시간 관련된 부분을 처리해주는 패키지 중 하나.

  • 요청 날짜 :2024.12.17
date_year = 2024
date_month = 12
date_day = 17
page = 1
  • 주소상 원하는 날짜에 대한 양식  YYYY.MM.DD
date = datetime.datetime( date_year, date_month,date_day)
date_YYYYMMDD = date.strftime("%Y.%m.%d") # 패키지에 대한 메뉴얼 참조 : 4자리 년도 %Y, %m
date_YYYYMMDD

url = f"https://dart.fss.or.kr/dsac001/mainAll.do?selectDate={date_YYYYMMDD}&currentPage={page}"
url

  • 셀레니움으로 접속을 해보자
path = r"C:\Users\kwonm\Downloads\chromedriver-win64\chromedriver.exe"
s = Service( path )
driver = webdriver.Chrome( service= s)
driver.get(url)

  • 참고) 지금 상황에서 driver 변수 안에 2024.12.17일 1페이지 모든 공시 정보가 있다
# driver.page_source : html -> 빠르게 정보 처리하기 위해서는 bs4
# BeautifulSoup( driver.page_source, "html.parser")

  • Q) 1번 공시의 시간에 대한 정보를 접근하고 출력해보자
//*[@id="listContents"]/div[2]/table/tbody/tr[1]/td[1]
/html/body/div[4]/div[2]/div[1]/div[2]/div[3]/div[2]/table/tbody/tr[1]/td[1]
# xpath에서 규칙이 보인다
# xpath로 정보를 접근해보자
b_path = '//*[@id="listContents"]/div[2]/table/tbody/tr[1]/td[1]'
temp = driver.find_element(By.XPATH, b_path)
temp.text

  • Q) 간단하게 공시 시간에 대한 정보만 앞의 5개 공시들에 대해서 출력해보자
    => for  : 위에서 찾은 공시 시간에 대한 부분에 접근 방식이 규칙화가 가능한지 체크
    # //*[@id="listContents"]/div[2]/table/tbody/tr[1]/td[1]
for i in range(1, 6):
    b_path = f'//*[@id="listContents"]/div[2]/table/tbody/tr[{i}]/td[1]'
    temp = driver.find_element(By.XPATH, b_path)
    print(temp.text)

  • Q) 1번 회사의 이름
co_path = '//*[@id="listContents"]/div[2]/table/tbody/tr[1]/td[2]/span/a'
temp = driver.find_element(By.XPATH, co_path)
temp.text
temp.get_attribute("href")
re.findall(r"\d{8}",temp.get_attribute("href") )[0]

  • Q) 1번 공시에 대한 이름을 출력해보자
  • xpath : //*[@id="r_20241217900785"]
    => 모든 공시에 대한 고유값을 알아야 한다
  • xpath 접근은 가능하지만 규칙화를 하는데 있어서는 불편하다
    full_xpath : /html/body/div[4]/div[2]/div[1]/div[2]/div[3]/div[2]/table/tbody/tr[1]/td[3]/a
    => 조금 더 규칙화에 용이하다
r_path = '/html/body/div[4]/div[2]/div[1]/div[2]/div[3]/div[2]/table/tbody/tr[1]/td[3]/a'
temp = driver.find_element(By.XPATH, r_path)
temp.text

  • Q) 1번 공시에 대한 rcpno를 찾아보자
r_path = '/html/body/div[4]/div[2]/div[1]/div[2]/div[3]/div[2]/table/tbody/tr[1]/td[3]/a'
temp = driver.find_element(By.XPATH, r_path).get_attribute("href")
re.findall(r"\d{14}", temp)[0]

  • 기존 tag 중심으로 찾을려면
driver.find_elements(By.TAG_NAME, "tr")[1].text
btn_path = '//*[@id="listContents"]/div[3]/div[2]/ul/li[2]/a'
driver.find_element(By.XPATH, btn_path).click()
time.sleep(3) # 3초 정도 대기하는 코드 -> 꼭 해야지만 정보가 들어올 때 발생한다
# 해당 사이트에서 나를 차단할 수 있어서 시간 지연을 줘야 한다 (실험필요)
len( driver.find_elements(By.TAG_NAME,"tr")) # ---> 갯수가 이상하게 들어올 때
# -> 101개 들어와야 하는데 적게 들어온다
# => driver 변수안에 정보가 충분히 안 담겨서 발생하는 현상

  • 정리
    - 일반적인 웹 사이트 : 개발자 도구 -> 네트워크 쪽 찾아보기!!
    + 헤더에 user-agent, refere etc
    + 웹브라이저를 통한 셀레니움 (브라우저 + 브라우저 버전에 맞는 webdriver) + bs4

    결론 : 본인이 수집해야하는 사이트에 맞춰서 해야한다 (그때그때 다르다)

    크롤링 : 어려운 부분 없다, 귀찮음은 있다, 찾아보고 실험도 해야 해서
    => 몇 번 해보면 감을 잡을 것