Day41_Python분석_39‐42 CSS,배포,스크래핑 - bonniekwon0721/Dataanalytics-study GitHub Wiki

20/APR/2024


10. 이론 - CSS 기초 1

CSS란?

Cascading Style Sheets

HTML, XML등의 마크업 언어로 작성된 문서를 꾸미는 스타일링 언어

레이아웃, 폰트, 색상, 간격 등을 제어

CSS는 쉽지 않습니다.

연관된 레이아웃을 묶어서 각 그룹의 위치를 지정해주는 방식으로 운영됩니다.

CSS 적용 방법

인라인 스타일

HTML 태그 내의 style 속성 사용 : 우선순위가 가장 높음 해당 요소에만 적용

⇒ 대부분의 HTML 태그에 style 속성 가능 ⇒ 몇몇 HTML 태그는 스타일 적용이 무의미/제한적 (head, title, meta,script 등) (!) 너무 많은 인라인 스타일은 코드가 복잡해질 수 있음! => 유지보수가 어려움

내장 스타일

HTML 문서의

에 <style> 태그 사용 • 한 문서 내의 모든 요소에 적용

외부 스타일

외부 CSS 파일을 HTML 문서에 연결 • 한 문서 내의 모든 요소에 적용 + 여러 문서에서 재사용 가능

11. 이론 - CSS 기초 2

Style의 종류

텍스트 스타일

⇒ h1~h6, p, b 등

p{
	color: red; # 텍스트 색상
	font-family: "Aria, sans-serif; # 사용 폰트
	font-size: 16px; # 텍스트 크기
	font-weight: bold; # 텍스트 두께
	text-align: center; # 텍스트 정렬방식
	text-transform: uppercase; # 대소문자
	line-height: 1.5; # 줄 높이
	letter-spacing: 1px;# 문자 간의 간격
}

레이아웃/박스 스타일

div {
	width: 300px; # 너비
	height: 200px; # 높이
	margin: 20px; # 외부 여백
	padding: 30px; # 내부 여백
	border: 1px solid black; # 테두리 (두께 타입 컬러)
	background-color: green; # 배경 색상
	color: white; # 텍스트 색상
	display: flex;# 디스플레이 타입
	justify-content: center; # 자식 요소들의 수평 정렬
	align-items: center; # 자식 요소들의 수직 정렬
}

Display의 종류

display: inline

⇒ span, b, i, a 등

• 상자 크기:
콘텐츠의 너비만큼만 차지 (높이, 너비 지정 불가)
• 줄 바꿈:
없음. 다른 인라인 요소나 텍스트와 같은 줄에 위치
• 용도:
주로 텍스트 스타일링에 사용

display:block

⇒ div, p, h1~h6, li 등

• 상자 크기:
가능한 한 부모 요소의 전체 너비를 차지 (높이, 너비 지정 가능)
• 줄 바꿈:
자동으로 줄 바꿈이 일어남
• 용도:
주로 구조와 레이아웃에 사용

display: inline-block

• 상자 크기:
가능한 한 부모 요소의 전체 너비를 차지 (높이, 너비 지정 가능)
• 줄 바꿈:
없음

display: flex

• 유연성: 아이템 간의 간격, 정렬을 유연하게 조절 가능
• 자식 요소들을 모두
inline-block으로 설정하는 것과 같은 효과

display: none

• 공간 차지: 화면에서 완전히 제거되어 어떠한 공간도 차지하지 않음
• 접근성: 스크린 리더에서도 읽히지 않음

12. 이론 - 개발자 도구

개발자 도구란?

  • 웹 브라우저 내장 도구
    • 크롬, 파이어폭스, 사파리, 엣지 등 => 개발자 도구(DevTools)의 비나 기능에 약간의 차이가 있을 수 있음
  • 웹 페이지의 작동 원리를 이해하고 디버깅하는 데 사용
  • 주요기능
    • HTML과 CSS를 실시간으로 확인하고 수정
    • 에러 메시지와 로그를 확인
    • 네트워크 통신과 관련된 정보 확인
    • 웹 페이지의 성능을 분석
    • 쿠키, 로컬 스토리지, 세션 스토리지 등 확인

13. 실습 - CSS로 이력서 꾸며보기 1

<!DOCTYPE html> <!--문서유형선언-->
<html>
    <head>
        <meta charset="UTF-8"/>
        <!--character set-->
        <link rel="stylesheet" href="style.css"/> # 여기서 연결
        <title>권보니 이력서</title>

chrome에서 미리보기 열어보기

선택한 섹션의 구문을 선택하면 해당 부분이 하이라이트 된다.

크롬 개발자 도구에서 Style을 시험해볼수도 있다.

body {
    margin: 20px;
    background-color:white;
}

header {
    background-color: #50b3a2;
    color: white;
    padding: 10px 0px 10px 0px ; 
    text-align: center;
}

h1 {
    margin: 10px 0;
}

14. 실습 - CSS로 이력서 꾸며보기 2

Chrome 에 display:flex를 넣어서 padding 테스트해보기

CSS 에서 마무리하기

body {
    margin: 20px;
    background-color:white;
}

header {
    background-color: #50b3a2;
    color: white;
    padding: 10px 0px 10px 0px ; 
    text-align: center;
}

h1 {
    margin: 10px 0;
}

main{
    display: flex;
    flex-direction: column;
    gap: 30px;
    background-color: whithe;
    margin: 20px;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0px 0px 10px rgba(0,0,0,0.1)
}

h2{
    background-color: rgb(65,65,65);
    color: white;
    padding: 10px;
    margin:0;
}

15. 이론 - 선택자 (Selector)

클래스 선택자와 아이디 선택자를 다루기 전에…

HTML의 Class속성

HTML 요소의 분류 및 그룹화에 사용

  • 사용 목적: 여러 요소에 동일한 스타일 및 JS 함수 적용
  • 특징:
    • 하나의 요소에 여러 클래스를 부여 가능
    • 하나의 클래스를 여러 요소에 적용 가능

HTML의 ID 속성

특정 HTML 요소에 고유한 식별자를 제공

  • 사용 목적: 특정 요소에 접근 및 스타일 적용
  • 특징:
  • 1D는 문서 내에서 유일해야함 (중복X)

클래스 선택자 (Class Selector)

클래스 이름를 기반으로 스타일을 적용

  • 적용 범위: 특정 클래스를 가진 모든 요소. 재사용 가능한 스타일을 정의할 때 유용.

아이디 선택자 (ID Selector)

아이디를 기반으로 스타일을 적용

  • 적용 범위: 특정 아이디를 가진 단 하나의 요소

콤비네이터(Combinators)

여러 요소를 결합하여 더 복잡한 선택 규칙을 생성

  • 자식 콤비네이터 (Child Combinator)

    ⇒ 특정 요소의 직계 자식만을 선택

  • 후손 콤비네이터 (Descendant Combinator)

    ⇒ 특정 요소의 모든 후손을 선택합니다.

16. 실습 - 선택자 (Selector) 1

선택을 위한 라벨링을 해주었습니다.

<!DOCTYPE html> <!--문서유형선언-->
<html>
    <head>
        <meta charset="UTF-8"/>
        <!--character set-->
        <link rel="stylesheet" href="style.css"/>
        <title>권보니 이력서</title>
    </head>
    <body>
        <header>
            <h1 id="name">권다영</h1>
            <p id="introduction">데이터를 통해서 비지니스 문제를 해결하고 가치를 창출하는 경험이 풍부한 데이터 분석가입니다.</p>
        </header>
        <main>
            <section class="main-section contact-section">
                <h2>Contact</h2>
                <p id="mobile"><b>Mobile:</b> 010-1234-5678</p>
                <p id="email"><b>E-MAIL:</b> [email protected]</p>
                <p id="address"><b>Address:</b> 서울시 송파구 보니로</p>
                <p><b>Social & Websites:</b>
                </p>
                <div id="socials-div">
                    <a id="linkedin_link" href="https://www.linkedin.com/">LinkedIn</a>
                    <a id="github_link" href="https://github.com/">GitHub</a>
                    <a id="instagram_link" href="https://www.instagram.com/">Instagram</a>
                </div>
            </section>
            <section class="main-section skills-section">
                <h2>Skills</h2>
                <ul><!--unordered list-->
                    <!--list item-->
                    <li>Phtyon</li>
                    <li>R</li>
                    <li>SQL</li>
                    <li>Tableau</li>
                    <li>Machine Learning</li>
                </ul>
            </section>
            <section class="main-section education-section">
                <h2>Education</h2>
                <ul>
                    <li>보니대학교 컴퓨터 공학과, 학사</li>
                    <li>보니대학교 데이터 사이언스, 석사</li>
                </ul>
            </section>
            <section class="main-section projects-section">
                <h2>Projects</h2>
                <!--ordered list-->
                <ol>
                    <li>고객 세그멘테이션을 위한 클러스터링 분석
                        <p>
                            이 프로젝트에서는 K-means 알고리즘을 사용하여 고객 데이터를 분석하고 세그먼트를 생성했습니다. 결과적으로 마케팅 팀이 타겟팅 전략을 더 효율적으로 수행할 수 있었습니다.
                        </p>
                    </li>
                    <li>시계열 데이터를 활용한 매출 예측 모델 개발
                        <p>
                            ARIMA 모델을 활용하여 회사의 분기별 매출을 예측했습니다. 이 모델은 실제 매출과 95%의 정확도로 일치하는 결과를 보였습니다.
                        </p>
                    </li>
                    <li>자연어 처리를 이용한 고객 리뷰 분석
                        <p>
                            고객 리뷰 데이터를 수집하여 감정 분석을 수행했습니다. 이를 통해 제품 개선 포인트와 고객 만족도를 측정할 수 있었습니다.
                        </p>
                    </li>
                </ol>
            </section>
        </main>
    </body>
</html>

17. 실습 - 선택자 (Selector) 2

p,ul,ol,h2 {
    margin: 0;
    padding: 0;
}

body {
    margin: 20px;
    background-color:white;
    font-size: 20px;

}

header {
    background-color: #50b3a2;
    color: white;
    padding: 10px 0px 10px 0px ; 
    text-align: center;
    line-height: 1.5;
}
#name {
    margin: 10px 0;
}

#introduction {
    font-size: 18px;
    margine: 20px;
}

main{
    display: flex;
    flex-direction: column;
    gap: 30px;
    background-color: whithe;
    margin: 20px;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0px 0px 10px rgba(0,0,0,0.1)
}

.main-section {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.main-section > h2 {
    background-color: rgb(65,65,65);
    color: white;
    padding: 10px;
    margin:0;
}

.contact-section {
    gap: 10px;
}

.contact-section > p {
    margin: 0 0 0 20px;
}

#socials-div {
    display: flex;
    justify-content: space-around;
}

ul, ol {
    padding: 0 20px;
}

.projects-section ol {
    list-style-type: upper-alpha;
}

18. 이론 - 웹페이지 배포하기

배포 옵션 간략 소개

자체 서버

직접 서버를 구축하고 관리

  • 제어력 높으나 관리가 복잡 (서버 유지보수, 보안 등)
  • Apache나 Nginx 같은 웹 서버 소프트웨어 사용

클라우드 서비스

이미 구축되어있는 서버를 일정기간, 원하는 만큼 빌려서 사용

  • 확장성과 관리 편의성이 뛰어나지만, 비용이 들 수 있음
  • Amazon AWS, Microsoft Azure, Google Cloud 같은 클라우드 서비스 이용

정적 사이트 호스팅

미리 만들어진 정적 웹 페이지를 호스팅하는 서비스

  • 설정이 간단하고 대부분의 경우 무료로 사용 가능
  • 동적인 기능(데이터베이스 연동, 서버 측 로직 등)에는 제한이 있을 수 있음
  • GitHub Pages, Netlify, Vercel 등과 같은 호스팅 서비스를 사용

GitHub Pages

GitHub에서 제공하는 무료 :) 정적 사이트 호스팅 서비스

  • 프로젝트의 README, 문서, 또는 개인 웹사이트를 간단하게 배포 가능
  • 설정이 매우 쉽고, 커스텀 도메인 연결도 가능 (= 내가 원하는 이름의 주소)
  • GitHub 저장소(Repository)와 직접 연동 => 코드 변경사항을 쉽게 웹에 반영할 수 있음

19. 이론 - 웹페이지의 동작 과정 (feat. Python) 1

HTTP 구성 요소

1. URL (Uniform Resource Locator)

웹 자원의 위치를 지정

프로토콜

  • HTTP: 데이터를 암호화하지 않고 그대로 전송 (보안 취약)
  • HTTPS:HTTP에 보안 계층 추가됨 (데이터 암호화. 안전성과 무결성 보장)

2. HTTP 메서드

  • GET
    • 데이터를 검색 (예: 페이지를 보여줘!)
  • POST
    • 데이터를 서버로 보내고 리소스 생성 (예: 신규 회원가입)
  • PUT
    • 데이터를 업데이트 (예: 회원정보 수정)
  • DELETE
    • 데이터를 삭제 (예: 회원 탈퇴)

3. HTTP 헤더

메타데이터와 설정 정보

  • 요청 헤더(Request Headers)
    • User-Agent: 클라이언트의 브라우저와 운영 체제 정보
    • Accept: 클라이언트가 수용할 수 있는 컨텐츠 유형
    • Authorization: 인증 토큰 또는 크리덴셜
  • 응답 헤더(Response Headers):
    • Content-Type: 반환되는 컨텐츠의 유형 (예: text/html, application/json)
    • Content-Length: 반환되는 컨텐츠의 길이
    • Set-Cookie: 쿠키 설정 정보

20. 이론 - 웹페이지의 동작 과정 (feat. Python) 2

4. HTTP 본문(Body)

클라이언트가 서버로 보내는 데이터

  • GET
    • GET 요청에서는 보통 본문이 없음 (필요시 주로 URL을 통해 데이터 전달)
  • POST, PUT
    • 추가 또는 업데이트할 데이터 (예: 폼데이터나 JSON 데이터 등의 형식)

5. 상태 코드 (Status Codes)

서버가 클라이언트의 요청을 어떻게 처리했는지를 나타내는 세 자리 숫자

  • 성공 응답 (Successful responses, 2xx)
    • 200 OK, 201 Created, 204 No Content
  • 클라이언트 에러 응답 (Client error responses, 4Xx)
    • 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
  • 서버 에러 응답 (Server error responses, 5xx)
    • 500 Internal Server Error, 501 Not Implemented, 502 Bad Gateway

브라우저의 역할 정리

  1. 서버에 요청을 보낸다 어떻게?
  2. 서버에서 웹페이지 생성에 필요한 파일들을 받는다
  3. 웹페이지의 구조(HTML)을 파싱(=읽고 이해)한다
  4. 웹페이지의 디자인(CSS)를 파싱(=읽고 이해)한다
  5. 이해한 HTML과 CSS정보를 합쳐서 화면에 보여준다

… 이후 생략

21. 이론 - Requests 라이브러리

Python HTTP Clients

  • Python에서 웹 서버와 HTTP/HTTPS 프로토콜을 사용하여 데이터 송수신

    == HTTP 요청을 만들어서 보내고 응답을 받는다

  • 용도: 웹 스크래핑, API 호출, 웹 서비스 통신 등

  • 종류:

    • requests 사용하기 쉽고, 다양한 HTTP 메서드를 지원. 복잡한 HTTP 작업도 간단하게 수행 가능.
    • urllib Python 표준 라이브러리에 포함된 모듈. API가 조금 더 복잡하고, 여러 모듈로 나뉘어져 있음
    • http.client Python 표준 라이브러리에 포함된 모듈. 매우 낮은 수준의 작업을 할 때 사용 == 높은 수준의 커스터마이징이 가능하지만, 사용이 복잡함.

22. 실습 - Requests - 웹페이지 Data Scraping

%pip install requests
import requests
url = "https://bonniekwon0721.github.io/bonnie_resume_test"
response = requests.get(url)
response
print(type(response))
print(type(response))
print('status code:',response.status_code)
print('contents:',response.content)
print('content type:',type(response.content))
print('text:',response.text)
print('test type:', type(response.text))

24. 실습 - BeautifulSoup 1 - prettify

%pip install bs4
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.content, 'html.parser')
type(soup)
print(soup.prettify())
# prettify 하면 HTML 문서처럼 들여쓰기가 된다.

24. 실습 - BeautifulSoup 1 - prettify

%pip install bs4
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.content, 'html.parser')
type(soup)
print(soup.prettify())
# prettify 하면 HTML 문서처럼 들여쓰기가 된다.

Untitled

25. 실습 - BeautifulSoup 2 - find

Tag.find(): 태그로 찾기

header_tag = soup.find("header")
print(header_tag)
print(type(header_tag))

Tag.fing(): id로 찾기

name_tag = soup.find(id="name")
name = name_tag.text
print(type(name_tag))
print(name)
print(type(name))

Tag.fing(): class로 찾기

전화번호 데이터 찾기

mobile_tag = soup.find(class_="contact-section").find('p') # find를 두번 쓸 때는 앞의 조건이 무조건 있을 대만 사용해야 한다.
mobile_text = mobile_tag.get_text(strip=True) # 공백을 없앨 수 있다.
mobile_number = mobile_text.split(':')[-1]
mobile_number
soup.find(class_="contact-section")

26. 실습 - BeautifulSoup 3 - find_all, find_parent

Tag.find_all() : 조건에 맞는 tag 모두 찾기

이메일 데이터 찾기

contact_section_tag = soup.find(class_="contact-section")
contact_tags = contact_section_tag.find_all("p")
type(contact_tags)

for idx,tag in enumerate(contact_tags):
    print(f'{idx}번째 p태그:',tag)
    
email_text = contact_tags[1].get_text(strip=True)
email = email_text.split(':')[-1]
email

Tag.fing_parent(): 부모 태그 찾기

주소 데이터 찾기

address_tag = soup.find('b', string="Address:").find_parent('p')
address = address_tag.get_text(strip=True).split(':')[-1]
print(address)
print('|'.join([name,mobile_number,email,address]))

27. 데이터 수집 방법 구상하기

  • 목표데이터는 리뷰 상세 페이지에서 제공함
  • 리뷰 상세 페이지는 리뷰 고유번호(review id)를 사용해서 url로 접근 가능

https://www.tripadvisor.co.kr/ShowUserReviews-g297885-d21364207-910624346-Grand_Hyatt_Jeju-Jeju_Jeju_Island.html

=먼저 리뷰 고유번호를 수집해야한다! 어떻게?

  • 호텔 리뷰 메인 페이지에는 1페이지당 5개 리뷰가 있음
  • 각 리뷰를 담고있는 div에는 리뷰 고유번호가 “data-reviewid”라는 클래스에 담겨 있음

⇒ 페이지별로 접근해서 리뷰 고유번호를 수집해서 리스트에 담으면 되겠다! 어떻게?

  • 호텔 리뷰 메인 페이지에 언어별 리뷰 개수가 있음
  • 각 페이지는 5배수로 증가하는 url 패턴을 가지고 있음

⇒ 찾고자하는 리뷰 전체 개수와 url패턴을 활용해서 각 페이지에 접근하면 되겠네~

데이터 수집 방법 1차 정리

  1. 메인 페이지 URL로 접근해서

(https://www.tripadvisor.co.kr/Hotel_Review-g297885-d21364207-Reviews-Grand_Hyatt_Jeju-Jeju_Jeju_Island.html)

  • 총 리뷰 개수를 구하고
  • 각 페이지에 리뷰가 5개씩있는점을 사용해서 총 페이지 수를 구하자
  1. URL 패턴을 사용해서 리뷰 첫 페이지부터 마지막 페이지까지 차근차근 접근해서

(https://www.tripadvisor.co.kr/Hotel_Review-g297885-d21364207-Reviews-or패턴-Grand_Hyatt_Jeju-Jeju_Jeju_/sland.html)

  • data-reviewid라는 클래스를 가진 div를 탐색해서
  • 클래스에 부여된 값(=리뷰 고유번호)를 수집 하자
  1. 리뷰 고유번호를 사용해서 리뷰 상세 페이지 URL로 접근해서

(https://www.tripadvisor.co.kr/ShowUserReviews-g297885-d21364207-r₴/##&-Grand_Hyatt_Jeju-Jeju_Jeju_/sland.html)

  • 목표데이터 14개에 접근하자! 어떻게?

28. Review ID 수집하기 1 - 스크래핑 준비하기

Imports

import requests
from bs4 import BeautifulSoup

Variables & Function

MAIN_BASE_URL = "https://www.tripadvisor.co.kr/Hotel_Review-g297885-d21364207-Reviews{}-Grand_Hyatt_Jeju-Jeju_Jeju_Island.html"

headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"}
def generate_main_url(page_num):
    '''페이지 번호를 입력 받아서 해당 트립어드바이저 리뷰 페이지에 접근할 수 있는 url을 반환합니다.'''
    if page_num == 1:
        return MAIN_BASE_URL.format("")
    return MAIN_BASE_URL.format("-or"+str((page_num-1)*5))

Scraping

# Scraping

[ STEPS ]
1. 메인 페이지 URL로 접근해서
(https://www.tripadvisor.co.kr/Hotel_Review-g297885-d21364207-Reviews-Grand_Hyatt_Jeju-Jeju_Jeju_Island.html)
- 총 리뷰 개수를 구하고
- 각 페이지에 리뷰가 5개씩있는점을 사용해서 총 페이지 수를 구하자

2. URL패턴을 사용해서 리뷰 첫 페이지부터 마지막 페이지까지 차근차근 접근해서
(https://www.tripadvisor.co.kr/Hotel_Review-g297885-d21364207-Reviews-or패턴-Grand_Hyatt_Jeju-Jeju_Jeju_Island.html)
- data-reviewid라는 클래스를 가진 div를 탐색해서
- 클래스에 부여된 값(=리뷰 고유번호)를 수집 하자

3. 리뷰 고유번호를 사용해서 리뷰 상세 페이지 URL로 접근해서
(https://www.tripadvisor.co.kr/ShowUserReviews-g297885-d21364207-r리뷰번호-Grand_Hyatt_Jeju-Jeju_Jeju_Island.html)
- 목표데이터 수집
  
[ 목표 데이터 ]

1. review_id (리뷰 고유번호 - 식별용)
2. member_id (리뷰 작성자 id - 식별용)
3. title (리뷰 제목)
4. rating_overall (종합 평점 - 5점 만점)
5. rating_date (리뷰 게시 날짜 - 년+월+일)
6. review_content (리뷰 내용)
7. stay_date (숙박 날짜 - 년+월)
8. trip_type (여행 유형)
9. rating_price (가격 평점)
10. rating_location (장소 평점)
11. rating_bed (침대의 퀄리티 평점)
12. rating_room (객실 평점)
13. rating_clean (청결도 평점)
14. rating_service (서비스 평점)
response = requests.get(generate_main_url(1),headers=headers)
response
soup = BeautifulSoup(response.content,'html.parser')
print(soup.prettify())

Studied from 제로베이스 데이터스쿨

⚠️ **GitHub.com Fallback** ⚠️