본문 바로가기
AI데이터 엔지니어, 새싹

73th_12_18(Mon)_Web Scrapping

by Leetora 2023. 12. 18.

데이터 분석가 핵심 역량 두 가지

Pasted image 20231218164314.png

  1. 왜 프로젝트를 시작했는지 설명하기
  2. 문제를 어떻게 정의하는지가 중요, 그래서 어떤 방법을 정의했는지가 중요

데이터 수집 방법

  1. SQL
  2. Open API
  3. 웹 스크레이핑

❓웹 스크레이핑

  • 인터넷 상의 웹 페이지를 자동으로 탐색해 정보를 추출하는 프로세스
  • 데이터 수집, 분석 및 처리를 자동화
  • 대표적 도구는 BeautifulSoup, Selenium

Robot.txt

  • 웹 스크레이핑을 할 때 해당 웹사이트의 =robots.txt= 를 통해 웹 크롤링에 대한 지침을 설명
  • 일반적으로 웹페이지의 URL에 /robots.txt를 추가해 해당 파일을 찾을 수 있음

정적 페이지 vs. 동적 페이지

  • 정적 페이지: 새로운 정보를 노출할 때 url이 변경
  • 동적 페이지: 새로운 정보를 노출할 때 url이 변경되지 않고 변동사항이 반영

웹 스페레이핑의 프로세스

   
장점 단점
Requests 빠름
BeautifulSoup 빠름
Selenium 1. 내외부 데이터 사용 가능

2. 모든 데이터를 가져올 수 있음

3. 브라우저 조작 가능

프로세스: 라이브러리 호출, URL 접속, HTML 받아오기, 정보 찾기, 저장하기 순으로 진행

       
방법1 방법2 방법3
라이브러리 호출 Requests Selenium Selenium
URL 접속 Requests Selenium Selenium
HTML 받아오기 Requests Selenium Selenium
정보찾기 BeautifulSoup Requests Selenium
저장하기(excel, csv, db)

❗️정적 스크레이핑 vs 동적 스크레이핑(Bot)

정적 스크레이핑

  • 웹 스크레이핑 프로세스 방법 : 1, 2
  • 정적 웹 스크레이핑은 웹 페이지의 HTML 코드를 가져와서 정보를 추출하는 방법
  • 이 방법은 대부분의 경우 적용 가능하지만, JavaScript와 같은 클라이언트 측 기술을 사용하여 동적으로 업데이트되는 웹 페이지에는 적용 불가

동적 스크레이핑

  • 웹 스크레이핑 프로세스 방법 : 3
  • 동적 웹 스크레이핑은 웹 페이지를 브라우저와 같은 방식으로 렌더링하여 정보를 추출하는 방법
  • 이 방법은 정적 웹 스크레이핑보다 더 많은 정보를 추출할 수 있으며, 클라이언트 측 기술을 사용하여 동적으로 업데이트되는 웹 페이지에 적용가능
  • 동적 웹 스크레이핑에는 Selenium(웹 브라우저를 제어하여 웹 페이지를 렌더링하고 정보를 추출하는 도구)과 같은 도구가 사용됨

데이터 분석을 위한 Source 분석

       
기준 SQL Open API 웹 스크레이핑
정의 관계형 데이터베이스 관리 시스템에서 데이터를 관리하는 언어 서로 다른 소프트웨어 간의 상호작용을 위한 규약 웹사이트에서 데이터를 추출하는 기술
주요 사용 사례 기업 데이터베이스, 고객 관리 시스템 등 소셜 미디어 데이터, 날씨 정보, 주식 시세 등 온라인 뉴스, 쇼핑 정보, 사용자 리뷰 등
장점 - 표준화된 언어 - 강력한 데이터 조작 기능 - 보안 - 용이한 통합 - 표준화된 데이터 형식 - 실시간 데이터 접근 - 유연성 - 비용 효율성
단점 - 데이터 접근 제한 - 학습 곡선 - API 제한 - 의존성 - 법적 문제 - 데이터 구조 변화에 취약 - 기술적 복잡성
SQL은 지속적으로 가져가야할 필요가 있음      

HTML

  • HTML은 Hyper Text Markup Language의 약자. 웹 페이지의 구조와 콘텐츠를 정의하는 마크업 언어. HTML은 브라우저에서 해석되어 사용자에게 웹 페이지가 어떻게 보이는지를 보여줌. HTML 태그를 사용하여 구조, 콘텐츠, 이미지, 비디오 등을 정의할 수 있음

HTML Element

  • =html= : HTML 문서의 루트 요소
  • =head= : 문서의 메타데이터를 포함하는 요소
  • =title= : 문서의 제목을 정의하는 요소
  • =body= : 문서의 본문을 포함하는 요소

부모와 자식 관계

  • HTML의 자식 요소는 HTML 태그 내에 중첩된 요소를 가리킴
  • 이 중첩된 요소는 자식 요소(child elements) 또는 하위 요소(descendants) 라고도 함
  • 예를 들어 body 태그는 header, nav, section, article, footer와 같은 다양한 자식 요소를 포함할 수 있음
  • 마찬가지로 ul 태그는 목록을 만들기 위해 li와 같은 자식 element를 포함할 수 있음
  • 자식 요소는 자체 자식 요소를 가질 수도 있으며, 계층 구조를 형성함

CSS

❓CSS(Cascading Style Sheets)

  • HTML로 작성된 콘텐츠의 스타일링을 가능하게 해주는 스타일 시트 언어
  • CSS를 사용하면 웹 개발자들은 문서의 내용과 디자인을 분리
  • 여러 웹 페이지의 디자인을 한 번에 유지·보수하고 수정할 수 있음

CSS Selector
HTML 요소를 스타일링하기 위해 선택하는 패턴. 선택자는 웹 페이지에서 특정 요소를 대상으로 CSS 스타일을 적용하는 데 사용

요소 선택자(Element Selector)

  • h1, p, ul과 같은 특정 유형의 모든 요소 선택

클래스 선택자(Class Selector)

  • .my-class와 같이 특정 클래스의 이름을 가진 요소 선택
  • ID 선택자(ID Selector) : #my-id와 같이 특정 ID를 가진 요소를 선택
  • 속성 선택자(Attribute Selector) : [type=“text”]와 같이 특정 속성 값이 있는 요소를 선택
  • CSS 클래스 : HTML 요소를 식별하기 위해 사용되는 이름으로, 여러 요소에 적용될 수 있으며, 동일한 클래스를 가진 요소는 동일한 스타일을 공유함. 클래스 이름은 대소문자를 구분하며, . 으로 시작합니다. 예를 들어, .my-class 클래스는 HTML 요소에 적용할 수 있음
<div class="my-class"> 이 요소는 my-class 클래스를 가지고 있습니다. </div> 

CSS ID

  • HTML 요소를 구체적으로 식별하기 위해 사용되는 이름으로, ID는 한 번만 사용할 수 있으며, HTML 문서에서 고유해야 함
  • ID 이름은 대소문자를 구분하며, #으로 시작함. 예를 들어, #my-id ID는 HTML 요소에 적용할 수 있음
  • CSS에서 ID를 선택할 때는 클래스와 유사하게 선택자를 사용함
  • 클래스와 ID는 CSS에서 미리 정의된 스타일을 적용하는 데 사용됨
  • 클래스는 여러 요소에서 공유할 수 있으므로, 스타일을 일관되게 적용하는 데 유용
  • ID는 한 번만 사용할 수 있으므로 보다 구체적인 스타일을 적용하는 데 유용함

<div id="my-id"> 이 요소는 my-id ID를 가지고 있습니다. </div> 

HTML vs JS vs CSS

  • HTML은 웹 페이지의 뼈대로, 구조와 내용을 정의
  • JavaScript는 웹페이지의 근육으로, 움직임과 반응을 제공하는 기능을 담당(웹 페이지를 동적으로 만들어줌)
  • CSS는 웹 페이지의 옷으로, 스타일과 외관을 제공하여 시각적으로 매력적이고 사용하기 쉬운 페이지를 만들어 줌(HTML로 작성된 콘텐츠의 디자인과 레이아웃을 관리할 수 있게 해줌)

정적 스크레이핑 실습 준비

#ⓐ requests 라이브러리 설치하기 ! pip install requests  #ⓑ 라이브러리 호출, URL 접속, HTML 받아오기 import requests # 라이브러리 호출  response = requests.get('https://www.naver.com') # URL 접속 print(response) print(response.text) # HTML 받아오기  #ⓒ beautifulsoup4 라이브러리 설치하기  ! pip install beautifulsoup4  #ⓓ beautifulsoup4 기본적인 사용 형태  from bs4 import BeautifulSoup  html_doc = ''' <html> <head> <title>웹 페이지 제목</title> </head> <body> <div id="content"> <h1>웹 페이지 내용</h1> <p>스크래핑을 위한 예시 문장입니다.</p> </div> </body> </html> '''   soup = BeautifulSoup(html_doc, 'html.parser')  title = soup.find('title')  h1 = soup.find('h1')  p = soup.find('p')  print(title.text)  print(h1.text) print(p.text) 

Naver Finance에서 인기 검색 종목 가져오기

# 라이브러리 호출  import requests from bs4 import BeautifulSoup   # URL 접속  response = requests.get('https://finance.naver.com/') print(response)   # HTML 받아오기  HTML = response.text soup = BeautifulSoup(HTML, 'html.parser')   # 정보 찾기  popular_stock_table = soup.find('div', class_ = 'aside_area aside_popular') popular_stock = popular_stock_table.find_all('tr', class_ = ['up', 'down', 'same'])   # 저장  stock_list = [] for i in range(len(popular_stock)):  	stock_name = popular_stock[i].find('a').text  	stock_list.append(stock_name)  stock_list 

<Response [200]> [‘LS머트리얼…’, ‘에코프로머티’, ‘에코프로’, ‘에코프로비엠’, ‘삼성전자’]

기상청 Top5 리스트 가져오기

# 라이브러리 호출  import requests  from bs4 import BeautifulSoup   # URL 접속  response = requests.get('https://www.weather.go.kr/w/index.do#dong/1120069000') print(response)   # HTML 받아오기  HTML = response.text soup = BeautifulSoup(HTML, 'html.parser')   # 정보 가져오기  	#1. find version top5 = soup.find('div', class_ = 'weblog-top10')  top5_list = top5.find_all('a', class_ = 'link')   	#2. select version top5 = soup.select_one('#lnb > div.tab > div.tab-item.on > div') top5_list = top5.select('a.link')  # 저장  result = []  for i in top5_list:  	result.append(i.text)  	result 

YES24 1P 책 제목 가져오기

import request from bs4 import BeautifulSoup  #URL 접속 response = requests.get('https://www.yes24.com/Product/Search?domain=ALL&query=%EC%9E%90%EC%97%B0%EC%96%B4%20%EC%B2%98%EB%A6%AC')  #HTML 받아오기 HTML = response.text soup = BeautifulSoup(HTML, 'html.parser')  #정보 가져오기 book_list_html = soup.select_one('#yesSchiList') book_list = book_list_html.select('a.gd_name')  title = [i.text for i in book_list] title  

네이버 금융 배당 페이지 웹 스크레이핑 후 데이터 프레임으로 만들기

import pandas as pd  # URL 접속 response = requests.get('https://finance.naver.com/sise/dividend_list.naver')  # HTML 받아오기 HTML = response.text soup = BeautifulSoup(HTML, 'html.parser')  # 정보 가져오기(컬럼) columns_html = soup.select_one('#contentarea_left > table.type_1.tb_ty > thead') columns_th = columns_html.select('th') columns = [i.text for i in columns_th] columns.remove('과거 3년 배당금')  # 정보 가져오기(로우) table_body = soup.select_one('#contentarea_left > table.type_1.tb_ty > tbody') row_html = table_body.select('tr') df_values = []  for i in range(len(row_html)):     if row_html[i].select_one('.txt').text != '\xa0':         title = row_html[i].select_one('.txt').text         values = [i.text for i in row_html[i].select('.num')]         result = [title] + values         df_values.append(result)  # for i in row_html: #     if i.select_one('.txt').text != '\xa0': #         title = i.select_one('.txt').text #         values = [i.text for i in i.select('.num')] #         result = [title] + values #         print(result)   # 데이터 프레임 만들기 df = pd.DataFrame(df_values, columns=columns) df.head()  

네이버 금융 배당 페이지 전체를 웹 스크레이핑 후 데이터 프레임으로 만들기

# 마지막 페이지 가져오기 # 속성에 있는 값에 접근할 때 .get 활용 last_page = int(soup.select_one('td.pgRR > a').get('href').split('&page=')[-1]) last_page  # 데이터 프레임으로 만들 수 있도록 함수 선언 def getPageData(page_num):     response = requests.get(f'https://finance.naver.com/sise/dividend_list.naver?&page={page_num}')          HTML = response.text     soup = BeautifulSoup(HTML, 'html.parser')      columns_html = soup.select_one('#contentarea_left > table.type_1.tb_ty > thead')     columns_th = columns_html.select('th')     columns = [i.text for i in columns_th]     columns.remove('과거 3년 배당금')      table_body = soup.select_one('#contentarea_left > table.type_1.tb_ty > tbody')     row_html = table_body.select('tr')     df_values = []       for i in range(len(row_html)):         if row_html[i].select_one('.txt').text != '\xa0':             title = row_html[i].select_one('.txt').text             values = [i.text for i in row_html[i].select('.num')]             result = [title] + values             df_values.append(result)      df = pd.DataFrame(df_values, columns=columns)      return df 
# 최종결과  empty_df = pd.DataFrame()   for i in range(1, last_page+1): 	empty_df = pd.concat([empty_df, getPageData(i)])  	 empty_df = empty_df.reset_index(drop=True) empty_df 

Pasted image 20231218194146.png

'AI데이터 엔지니어, 새싹' 카테고리의 다른 글

75th_12_20(Wed)_API활용 웹 크롤링  (1) 2024.01.08
70th_12_14(Mon)_시계열 데이터 분석  (0) 2024.01.08
62th_121_Overfitting  (0) 2023.12.04
61th_11_30(Thu)_ResNet  (1) 2023.11.30
60th_11_29(Wed)_GoogLeNet  (0) 2023.11.29