Web Data

이상해씨·2021년 10월 2일
0

EDA, 웹크롤링

목록 보기
6/13

◼Beautiful Soup

  • HTML : 웹 페이지를 구성하는 마크업 언어
    • html 태그 : 웹 페이지 표현
    • head 태그 : 눈에 보이지 않지만 문서에 필요한 헤더 정보 보관
    • body 태그 : 눈에 보이는 정보 보관
    • Beautiful Soup 테스트를 위해 html 작성
  • Beautiful Soup : 태그로 이루어진 문서를 해석하는 기능을 가진 모듈
    • html.parser : Beautiful Soup의 html을 읽는 엔진 중 하나(lxml도 많이 사용)
      • html.parser, lxml, lxml-xml, xml, html5lib 등
    • prettify() : html을 태그 기준으로 들여쓰기를 통해 정리해주는 기능
    • 모듈 설치 : pip install beautifulsoup4 | conda install -c beautifulsoup4
    • 공식 문서 : https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.html
from bs4 import BeautifulSoup
# 직접 작성한 html로 실험
page = open('../data/03. bs4_test.html', 'r').read()
soup = BeautifulSoup(page, "html.parser")
print(soup.prettify())

  • 태그 키워드 활용
    • 원하는 태그를 키워드로 선택할 수 있다. 처음 만나는 태그만을 선택한다.
    • head 키워드 : head 태그를 선택
    • body 키워드 : body 태그를 선택
    • p 키워드 : p 태그를 선택
# soup.body
soup.p
# soup.html

  • find, find_all
    • 원하는 태그를 찾을 수 있다.
    • 클래스를 이용할 수 있다.
    • 아이디를 이용할 수 있다. 아이디는 중복이 없다.
    • 조건은 다중으로 사용할 수 있다.
    • 속성은 dict형으로 사용할 수 있다.
      • {'class' : CLASS, 'id' : ID ...}
# 태그 찾기
soup.find("p")

# 모든 태그 찾기
soup.find_all('p')

# 클래스로 찾기
soup.find_all(class_= 'outer-text')
# soup.find_all({'class' : 'outer-text'})

# 아이디로 찾기
soup.find_all(id = 'first')
# soup.find_all({'id' : 'first'})

  • 텍스트 키워드 : 태그에 포함된 텍스트 반환
    • text 키워드 : 태그에 포함된 텍스트를 반환
    • string 키워드 : 태그에 포함된 텍스트를 반환(단, 단일 태그인 경우에만 동작)
    • get_text() : 태그에 포함된 텍스트를 반환
      • 텍스트가 여러 개 있다면 태그를 기준으로 개행되어 반환
      • '구분자' : 태그 사이의 구분자 설정
      • strip 옵션 : 데이터의 양끝 공백 제거 설정(True / False)
    • stripped_strings 키워드 : for을 사용하여 리스트, 튜플 등의 형태로 반환할 수 있다.
# 텍스트 속성 출력
for each_tag in soup.find_all('p'):
    print('-'*40)
    print('1.', each_tag.get_text())
    print('2.', each_tag.text)
    print('3.', each_tag.string)

  • 외부로 연결되는 링크의 주소 알아내기
    • find("a")로 링크 태그를 찾는다.
    • attrs 키워드 : 해당 태그의 속성 dcit형으로 반환
    • 태그[속성], 태그.get(속성) : 해당 태그의 속성 값 반환
links = soup.find_all('a')
for each in links:
    print('attrs : {}'.format(each.attrs))
    # href = each.get("href")
    href = each["href"]
    text = each.string
    print('1. ' + text + " -> " + href)
    text = each.get_text()
    print('2. ' + text + " -> " + href)
    text = each.text
    print('3. ' + text + " -> " + href)


◼크롬 개발자 도구

  • 크롬 개발자 도구를 활용해 찾고자 하는 데이터의 태그, 클래스, 아이디 등 정보 확인
    • 소스 코드를 통해 확인할 수 있다.
  • urllibrequest 모듈 : 웹주소에 접근하기 위해 사용하는 모듈
    • urlopen() : url로 웹 페이지를 요청하는 함수
    • status 키워드 : http 상태 코드로 200일 경우 정상적으로 정보를 받았다는 의미
    • http 상태 코드
from bs4 import BeautifulSoup
from urllib.request import urlopen

1. 네이버 금융 : 환율 확인

# url = 'http://info.finance.naver.com/marketindex/' ## url error
# 크롬 도구로 환율의 값이 담긴 태그와 클래스가 span, value임을 확인
url = 'https://finance.naver.com/marketindex/'
page = urlopen(url)
# .status 키워드 : http 상태 코드로 200일 경우 정상적으로 정보를 받았다는 의미

soup = BeautifulSoup(page, 'html.parser')
print(page.status)
print(soup.prettify())

# 환율 정보
soup.find_all("span", class_="value"), len(soup.find_all("span", class_="value"))

# 미국 환율 정보
# string/text/get_text()/getText() : 텍스트
soup.find_all("span", class_="value")[0].string 

2. 네이버 금융 : 환전 고시 환율

  • requests 모듈 사용
    • get(), post() 모드가 있다.
    • 웹 페이지를 해당 명령으로 열게되면 http 상태 코드를 확인할 수 있다.
    • text 키워드 : 웹 페이지의 내용 반환
# 환전 고시 환율
# 환율, 등락, 링크
url = 'https://finance.naver.com/marketindex/'
response = requests.get(url) # 웹의 내용은 이미 담겨있다.
soup = BeautifulSoup(response.text, 'html.parser')
print(soup.prettify())

  • find, select_one : 단일 선택
  • find_all, select : 다중 선택
# 데이터 추출
# soup.find_all("li", class_ = 'on') : 태그와 클래스는 중복이 가능하므로 
# 				       원하지 않는 데이터도 추출될 수 있다.
# class : .클래스 (>) 태그 - 클래스 소속 중 해당 태그 선택
# id : #아이디 (>) 태그 - 아이디 소속 중 해당 태그 선택
# tag : 태그 - 태그 선택
# 꺽쇠(>) : 해당 클래스, 아이디의 바로 하위를 의미(>가 없다면 깊이 우선 탐색을 하게 된다.)
# 아이디 : exchangeList 하위의 li 태그 추출
exchangeList = soup.select("#exchangeList > li")
len(exchangeList), exchangeList

# 데이터 추가 추출
title = exchangeList[0].select_one('.h_lst').text
print(title)
exchange = exchangeList[0].select_one('.value').text
print(exchange)
change = exchangeList[0].select_one('.change').text
print(change)
# head_info point_(up/dn)
# 공백이 들어간 클래스는 공백을 기준으로 클래스가 2개임을 의미한다.
# 따라서 head_info, point_(up/dn) 2가지를 가지게 된다.
# 여기서 point_up 또는 point_dn은 값에 따라 다르게 되므로 head_info로만 값을 찾는다.
updown = exchangeList[0].select_one('div.head_info > .blind').text
print(updown)
baseUrl = 'https://finance.naver.com'
link = baseUrl + exchangeList[0].select_one('a').get('href')
print(link)

  • 환전 고시 환율 추출
# 4개의 데이터 수집
exchangeDatas = []
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('div.head_info > .blind').text,
        'link' : baseUrl + item.select_one('a').get('href')
    }
    exchangeDatas.append(data)
df = pd.DataFrame(exchangeDatas)
df.to_excel('./naverfinance.xlsx', encoding='utf-8')
df


◼위키백과 활용

# import
import urllib
from urllib.request import urlopen, Requests

# 웹 페이지 연결
html = "https://ko.wikipedia.org/wiki/{search_words}"
# urllib.parse.quote() : utf-8로 인코딩
req = Request(html.format(search_words=urllib.parse.quote("여명의_눈동자")))

response = urlopen(req)

soup = BeautifulSoup(response, "html.parser")
print(soup.prettify())

# 주요 인물 부분의 태그 확인
# ul임을 확인
# 16 번째 ul이 원하는 정보를 가지고 있음을 확인(인덱스는 0부터 시작)
n = 0
for each in soup.find_all('ul'):
    print('=>' + str(n)+"=================================")
    print(each.get_text('|', strip=True))
    n += 1

# 데이터 추출
# replace 함수를 이용해 필요없는 부분 제거
soup.find_all('ul')[15].text.replace('\xa0', '').replace('\n', ' ')

profile
후라이드 치킨

0개의 댓글