Ch4 웹데이터 분석 01-13 (웹데이터1-3)

김민지·2023년 3월 31일
0
  1. Beautiful Soup 기초
  • 터미널에서 ds_study루트로 간 다음에 code . -> Visual Studio Code 실행

  • ctrl+shift+p 누르고 python select interpreter -> ds_study 선택해서 연결해주기

  • html 만들기

  • : 인터넷 탭 제목 설정가능 (제목)
  • href="링크주소"

<!DOCTYPE html>
<html>
    <head>
        <title>Very Simple HTML Code by MJ</title>
    </head>
    <body>
        <div>
            <p class="inner-text first-item" id="first">
                Happy ZeroBase.
                <a href="http://www.pinkwink.kr" id="pw-link">PinkWink</a>
            </p>
            <p class="inner-text second-item">
                Happy Data Science.
                <a href="https://www.python.org" target="_blink" id="py-link">Python</a> # '_blink' : 새 창에서 열기
            </p>
        </div>
        <p class="outer-text first-item" id="second">
            <b>Data Science is funny.</b> # 볼드체
        </p>
        <p class="outer-text">
            <i>All I need is Love.</i>  # 이탈릭체
        </p>
    </body>

</html>
  • 만든 html에서 데이터 추출하기(BeautifulSoup 이용)

-> 설치:
conda install -c anaconda beautifulsoup4
or
pip install beautifulsoup4

# import
from bs4 import BeautifulSoup
page = open("../data/03. minji.html", "r").read()
soup = BeautifulSoup(page, "html.parser")
print(soup.prettify())   # 코드가 보기 편하게 표현됨
# head 태그 확인
soup.head
# body 태그 확인
soup.body
# 태그 p 확인
# 처음 발견한 p 태그만 출력
# find()
soup.p
soup.find("p")
# 파이썬 예약어 -> 안 겹치도록 해야
# class, id, def, list, str, int, tuple...
soup.find("p", class_="inner-text first-item")  # class 지정으로 원하는 p를 찾을 수 있음
soup.find("p", {"class":"outer-text first-item"}).text.strip()

-> 'Data Science is funny.'처럼 텍스트를 깔끔하게 가져옴

# 다중 조건
soup.find("p", {"class":"inner-text first-item", "id":"first"})
# find_all() : 여러개의 태그를 반환함
# list 형태로 반환

soup.find_all("p")
# 특정 태그 확인
# list의 text를 가져오기 위해선 인덱스도 지정해줘야 함

soup.find_all(class_="outer-text")[0].text
print(soup.find_all("p")[0].text)
print(soup.find_all("p")[1].string)
print(soup.find_all("p")[1].get_text())

-> 텍스트 가져오는 여러 방법

# p 태그 리스트에서 텍스트 속성만 출력

for each_tag in soup.find_all("p"):
    print("=" * 50)
    print(each_tag.text)
# a 태그에서 href 속성값에 있는 값 추출

links = soup.find_all("a")
print(links)
links[0].get("href"), links[1]["href"]

-> PinkWink, Python

for each in links:
    href = each.get("href") # each["href"]
    text = each.get_text()
    print(text + " => " + href)

-> PinkWink => http://www.pinkwink.kr
Python => https://www.python.org

  1. 크롬 개발자 도구 이용하기
  • 크롬 개발자도구를 통해 html 코드를 쉽게 확인 가능
# import
from urllib.request import urlopen
from bs4 import BeautifulSoup
url = "https://finance.naver.com/marketindex/"
page = urlopen(url)
soup = BeautifulSoup(page, "html.parser")
print(soup.prettify())
  • page 말고도 response, res라는 변수도 자주 쓰이는데, request모듈을 사용해서 네이버에 요청을 하고, 요청받은 것(url)을 response에 담아서 사용함
    -> response.status -> HTTP 상태 코드를 반환함(숫자로 알려줌)

  • 크롬 개발자도구를 이용해서 찾고자 하는 데이터의 코드 확인 후 검색

# 1
soup.find_all("span", "value"), len(soup.find_all("span", "value"))
# 2
soup.find_all("span", class_="value")
# 3
soup.find_all("span", {"class":"value"})
soup.find_all("span", {"class":"value"})[0].text, soup.find_all("span", {"class":"value"})[0].string

-> ('1,298.50', '1,298.50')

find, select_one : 단일 선택
select, find_all : 다중 선택

import requests
# from urllib.request.Request
from bs4 import BeautifulSoup
url = "https://finance.naver.com/marketindex/"
response = requests.get(url)
# response.get(), response.post()
soup = BeautifulSoup(response.text, "html.parser")
print(soup.prettify())
# soup.find_all("li", "on")
# id -> 앞에 # 붙이기
# class -> 앞에 . 붙이기

exchangeList = soup.select("#exchangeList > li") # id의 li를 모두 가져옴
len(exchangeList), exchangeList
title = exchangeList[0].select_one(".h_lst").text
exchange = exchangeList[0].select_one(".value").text
change = exchangeList[0].select_one(".change").text
updown = exchangeList[0].select_one(".head_info.point_dn > .blind").text

title, exchange, change, updown

-> ('미국 USD', '1,298.50', ' 4.50', '하락')

  • '>' : 해당 클래스의 바로 하위의 값을 가져옴
# findmethod = soup.find_all("ul", id="exchangeList")
# findmethod[0].find_all("span", "value")
baseUrl = "https://finance.naver.com"
baseUrl + exchangeList[0].select_one("a").get("href")

-> 'https://finance.naver.com/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW'

import pandas as pd
# 4개 데이터 수집

exchange_datas = []
baseUrl = "https://finance.naver.com"

for item in exchangeList:
    data = {
        "title": item.select_one(".h_lst").text,
        "exchange": item.select_one(".value").text,
        "change": item.select_one(".change").text,
        "updown": item.select_one(".head_info.point_dn > .blind").text if (item.select_one(".head_info.point_dn > .blind") != None) else item.select_one(".head_info.point_up > .blind").text,        
        "link": baseUrl + item.select_one("a").get("href")
    }
    exchange_datas.append(data)
df = pd.DataFrame(exchange_datas)  # 데이터프레임으로 만들기
df.to_excel("./naverfinance.xlsx", encoding="utf-8")  # 엑셀파일로 저장
  1. 위키백과 문서 정보 가져오기
  • '여명의 눈동자' 위키백과에서 주요인물 정보 가져오기
import urllib
from urllib.request import urlopen, Request

html = "https://ko.wikipedia.org/wiki/{search_words}"
req = Request(html.format(search_words=urllib.parse.quote("여명의_눈동자"))) # 글자를 URL로 인코딩
response = urlopen(req)
soup = BeautifulSoup(response, "html.parser")
print(soup.prettify())

-> 한글주소를 바로 가져오면 깨지기 때문에 decoding을 해서 가져오던가, url로 인코딩하는 Request과정을 거치던가

n = 0

for each in soup.find_all("ul"):
    print("=>" + str(n) + "=====================")
    print(each.get_text())
    n += 1

-> 가지고 오고자 하는 데이터를 특정하기 위해, "ul"이 많기 때문에 for문을 돌려서 몇 번째 "ul"인지 찾아내기

soup.find_all("ul")[32].text.strip().replace("\xa0", "").replace("\n", "")

-> 32번째 "ul"을 가져오고, 필요없는 문자열 없애기

  1. list 데이터형
  • list형은 대괄호로 생성
colors = ["red", "blue", "green"]
b = colors   # 원본도 바뀜
b[1] = "black"

-> ['red', 'black', 'green']

colors  

-> ['red', 'black', 'green']

c = colors.copy()   # 원본은 바뀌지 않음
c[1] = "yellow"
colors   

-> ['red', 'black', 'green']

  • list형을 반복문(for)에 적용
for color in colors:
    print(color)
  • in명령으로 조건문(if)에 적용
if "black" in colors:
    print("True")
movies = ["라라랜드", "먼 훗날 우리", "어벤져스", "다크나이트"]
  • append : list 제일 뒤에 값을 하나 추가함
movies.append("타이타닉")
  • pop : list 제일 뒤부터 자료를 하나씩 삭제
movies.pop()
  • extend : list 제일 뒤에 자료를 추가(여러개 가능)
movies.extend(["위대한쇼맨", "인셉션", "터미네이터"])
  • remove : 지정한 자료를 삭제
movies.remove("어벤져스")
  • 슬라이싱 : [n:m] n번째부터 m-1까지
favorite_movies = movies[3:5]
  • insert : 원하는 위치에 자료를 삽입
favorite_movies.insert(1, 9.6)
favorite_movies.insert(3, 9.5)
  • list 안에 list 가능
favorite_movies.insert(5, ["레오나르도 디카프리오", "조용하"])
  • isinstance : 자료형 True/False로 반환
isinstance(favorite_movies, list)
for each_item in favorite_movies:
    if isinstance(each_item, list):
        for nested_item in each_item:
            print("nested_item", nested_item)
    else:
        print("each_item", each_item)

-> 리스트 안의 리스트 안의 값들도 하나씩 출력하는 방법

<제로베이스 데이터 취업 스쿨>

0개의 댓글